项目 |
内容 |
这个作业属于哪个课程 |
https://www.cnblogs.com/nwnu-daizh/ |
这个作业的要求在哪里 |
https://www.cnblogs.com/nwnu-daizh/p/11605051.html |
学习目标 |
|
第一部分 基础理论知识
- 类、超类和子类
(1)定义子类
关键字extends表示继承。
以由Employee类来定义Manager类为例:
Public class Manager extends Employee
{
添加方法和域
}
Extends表明正在构造的新类派生与一个已经存在的类。已存在的类称为父类或超类,新类称为子类或派生类。子类比超类拥有更加丰富的功能。以上面的例子为依据:Manager中含有setBonus,因而属于Employee类的对象不能使用它。然而属于Manager的对象可以使用属于Employee类中定义的,这是因为子类会自动继承父类中的方法。因此可以将通用的方法放在超类中而将具有特殊用法的放在子类中。
(2)覆盖方法
如果在父类中定义的方法在子类中不适用时,需要提供新的方法来覆盖父类中的这个方法。当我们需要调用父类中的某个方法时可以用关键字super来调用。(super只是一个指示编译器调用超类方法的特殊关键字)在子类中可以增加域,增加方法或覆盖超类的方法,可是绝对不能删除继承的任何域和方法。方法覆盖只能在不同的类中完成。
(3)子类的构造
通常我们可以通过super实现对超类构造器的调用。使用super调用构造器的语句必须是子类构造器的第一条语句。如果子类的构造器没有显示的调用父类构造器,则将自动的调用父类默认的构造器(没有参数)如果父类没有不带参数的构造器,而且子类没有其它的构造器,则将显示程序错误。
一个对象变量可以指示多种实际类型的现象被称为多态。在运行时能够自动地选择调用哪个方法的现象称为动态绑定。
(4)继承层次
由一个公共父类派生出来的所有类的集合被称为继承层次。在继承层次中,在某个特定的类到其祖先的路径被称为该类的链。通常一个祖先类可以拥有多个子孙继承链。由一个祖先类派生出来的几个子类之间可以没有任何关系。
(5)多态
“is-a”规则表明每个子类的对象也是父类的对象,同样,它也表明程序中出现超类对象的任何地方都可以用子类对象置换。不能将一个超类的引用赋予子类变量。子类数组的
引用可以转化成为父类数组的引用,而不需要强制类型的转化。
- 第四章重点概要
(1)类是具有相同属性和行为的一组对象的抽象定义,用class来定义,对象是类的实例:
(2)类的语法格式是:对象名.成员名;
(3)使用预定义类要了解该类的API和类所属的包。
(4)构造函数在创建对象时初始化对象,构造函数课重载;
(5)Static可定义静态域和静态方法。
(6)包是分类组织类的主要手段,包对应磁盘上同名的目录。
(7)类所属的包课在类内用package来声明,可用import来导入需要使用类的包。构造方法在对象创建时被调用,用于初始化对象,初始化动作只执行一次;
(8)一般方法需对象创建后被调用执行,可以被调用多次。
(9)封装(面向对象特征之一)是指隐藏对象的属性和显示细节,仅对外提供公共访问方式,它的好处在于便于对象的使用,提高重用,安全性。
(10)This:代表对象,就是所在方法所属对象的引用。
——this对象后跟,调用成员属性和成员方法(一般方法):
——this对象后面跟上()调用本类中对应参数的构造方法
(11)static修饰符:
类中属于所有对象共享的数据或方法,可进行静态修饰。
被静态修饰的类成员,可以直接被类名所调用: 类名..静态成员名
静态类成员随着类的加载而加载。
静态方法只能访问静态成员,不可以访问非静态成员。静态方法中不能使用this,supper关键字。
2.继承
继承:用已有类来构建新的类的一种机制。当定义了一个新类继承了一个类时,这个新类就继承了这个类的方法和域,同时在新类中添加新的方法和域以适应新情况。
(Java不支持多继承)一个子类可以有多个父类,但一个父类只有一个子类。以
以下程序为例:
图中关键字表明了继承的特点。
3.多态性
(1)多态性的概念:
a.多态性泛指在程序中同一个符号在不同的情况下有不同解释的情况。
b.父类中定义的域方法,被子类继承之后,可以具有不同的数据类型或表现出不同的行为。
C.使在父类及其各个子类中同名的域或方法具有不同的语义。
d.父类的方法可以在子类重写
(2)多态性的示例:
shape类自行定义示例
调用父类方法和调用子类方法的关键词
父类:rectObj.getPerimeter();
子类:sqObj.getPerimeter();
4.抽象类
(1)观察类的继承层次结构,位于上层的累更具有通用性,甚至更加抽象。
定义抽象类的方法(关键字)示例:
abstract class Person
{
Public abstract String getDescription();
......
}
abstract方法只能声明,不能实现!
(2)为了提高程序清晰度,包含一个或多个抽象方法的类本身必须被声明为抽象类。除了抽象方法之外,抽象类还可以包含具体数据和具体方法。
(3)抽象方法还充当着占位的角色,他们的具体实现在子类中。
(4)抽象类不能被实例化,既不能创建对象,只能产生子类。可以创建抽象类的对象变量,只是这个变量必须指向它的非抽象子类的对象。
5.动态绑定
动态绑定又称为运行时绑定,即在运行程序时会自动选择调用哪个方法。
Public class Son extends Father
{......}
Son son=new Son();
Son.method();
6.调用方法的执行过程
首先,编译器检查对象的声明类型和方法名,找出所有访问属性为public和method的方法。
编译器检查方法调用中提供的参数类型,找出一个完全匹配方法,这个过程称为重载解析。
如果方法是private、static、final修饰的,或者是构造器,那么编译器能准确的判断应该调用哪个方法,这成为静态绑定。程序运行时现在子类找相应方法,
如果子类没有定义的相应的方法,则在父类的method()中寻找。
方法的名称和参数列表称为方法的签名。
7.阻止继承:final类和方法
不允许继承的类称为final类,在类的定义中用final修饰符加以说明。
Final class Executive extends Manager
{......}
类的方法可定义为final的。这是子类就不能用覆盖方法。
如果一个类声明为final,属于它的方法会被自动设为final,但不包括域(如果域定义为Final,在对象构造以后就不能修改)
Private final int Max=100;
String类是final的一个例子。不能狂战该类。
8.强制类型转换
如果要把一个超累对象赋给一个子类对象变量,就必须进行强制类型转化,格式为
子类 对象 = (子类)(超类对象)
9.访问权限修饰符
10.访问修饰符示例
11.访问修饰符可访问性
12.Object:所有类的超类
Object是Java所有类的祖先——每一个类都由它开展而来,在不给出超累的情况下,Java会自动把Object作为要定义的超类。可以使用类型为Object的变量指向任意类型的变量。
13.equals方法:用来检测两个对象状态的相等性时需要在心类中定义需要覆盖equals方法。
定义子类的equals方法时,可调用超累的equals方法:super.equals(otherObject)
14.toString方法
Object类的toString方法返回一个代表该对象值域的字符串。
定义子类的toString方法时,可先调用超类的toString方法。例Super.toString()
15.泛型数组列表
Java中,利用ArrayList类,可允许程序在运行时确定数组的大小。
ArrayList是一个采用参数类型的泛型类。为指定数组列表保存元素的对象类型。例:
ArrayList
16.ArrayList定义
(1)ArrayList
例如:ArrayList
(2)API:ArrayList的构造器
-ArrayList
-ArrayList
B.一下为集中情况:
17.对象包装器域自动打包
所欲基本数据类型都有与之相对应的预定义类,它们被称为对象包装器。
Integer Long Float Double Short Byte Character Void Booleaan
对象包装器时不可变的,即一旦构造了包装器,就不允许更改包装在其中的值。且对象包装器还是final,因此不能定义他们的子类。
使用对象包装器的好处:
-羁绊对象转换为对象
-定义一些有用的基本方法(Static方法)
将可以自动的将基本数据类型转换为包装器的对象称为自动打包。
打包和拆包时编译器认可的。
18.参数数量可变的方法
用户自己可以定义可变参数的方法,并将参数指定为任意类型,甚至是基本类型。例:
19.枚举类
(1)声明枚举类
例 Public enum Grade(A,B,C,D,E) 它包括一个关键字enum。
(2)枚举类是一个类,它的隐含超类是Java.Lang.Enum.
枚举类并不是整数类型或其他类型,是被声明的枚举类的自身实例。
枚举类不能有public修饰的构造函数,构造函数都是隐含praviate,编译器自动处理。枚举值隐含都是由public、static、final修饰的,无需自己添加这些修饰符。
在比较两个枚举类型的值时,永远不需要调用equals方法,直接使用“==”进行相等比较。
(3)为枚举类增加构造函数
第二部分 实验部分
1、实验目的与要求
(1) 理解继承的定义;
(2) 掌握子类的定义要求
(3) 掌握多态性的概念及用法;
(4) 掌握抽象类的定义及用途。
实验1: 导入第5章示例程序,测试并进行代码注释。
测试程序1:
在elipse IDE中编辑、调试、运行程序5-1 —5-3(教材152页-153页) ;
掌握子类的定义及用法;
结合程序运行结果,理解并总结OO风格程序构造特点,理解Employee和Manager类的关系子类的用途,并在代码中添加注释;
删除程序中Manager类、ManagerTest类,背录删除类的程序代码,在代码录入中理解父类与子类的关系和使用特点。
5-1程序源代码为:
package inheritance; /** * This program demonstrates inheritance. * @version 1.21 2004-02-21 * @author Cay Horstmann */ public class ManagerTest { public static void main(String[] args) { // construct a Manager object var boss = new Manager("Carl Cracker", 80000, 1987, 12, 15); boss.setBonus(5000);//创建一个新经理,并设置他的奖金,setBonus属于manager的特有方法 var staff = new Employee[3];//定义一个包含三个雇员的数组 // fill the staff array with Manager and Employee objects staff[0] = boss; staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1); staff[2] = new Employee("Tommy Tester", 40000, 1990, 3, 15); //父类引用子类对象;并将经理和雇员放入数组中 // print out information about all Employee objects for (Employee e : staff) System.out.println("name=" + e.getName() + ",salary=" + e.getSalary()); //输出每个人的姓名及薪水 } }
输出结果截图为:
5-2程序代码为:
package inheritance; import java.time.*; public class Employee { private String name; private double salary; private LocalDate hireDay; //构建成员变量 //构造器 public Employee(String name, double salary, int year, int month, int day) { this.name = name; this.salary = salary; hireDay = LocalDate.of(year, month, day); } //域访问器 public String getName()//取得name这个属性的值 { return name; } public double getSalary()//取得Salary这个属性的值 { return salary; } public LocalDate getHireDay() { return hireDay; } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } }
输出结果截图为:
5-3程序代码为:
package inheritance; public class Manager extends Employee { private double bonus; /** * @param name the employee's name * @param salary the salary * @param year the hire year * @param month the hire month * @param day the hire day */ //构造器 public Manager(String name, double salary, int year, int month, int day) { super(name, salary, year, month, day);//调用超类构造器 bonus = 0; } public double getSalary() { double baseSalary = super.getSalary();//进行重定义 return baseSalary + bonus; } public void setBonus(double b) { bonus = b; } }
输出结果截图为:
删除类的程序代码为:
package inheritance; public class Manager extends Employee { private int bouns; public Manager(String name, double salary, int year, int month, int day) { super(name, salary, year, month, day); // TODO Auto-generated constructor stub bouns=0; } public int getBouns() { return bouns; } public void setBouns(int bouns) { this.bouns = bouns; } @Override public double getSalary() { // TODO Auto-generated method stub return super.getSalary(); } }
关键在于@Override,它的引入为在source里面点Override,然后引入程序中需要的,例如上面程序中继承的为父类的getSalary()。继承的有点在于是程序看起来整洁,清晰。
输出结果截图为:
测试程序2:
编辑、编译、调试运行教材PersonTest程序(教材163页-165页);
掌握超类的定义及其使用要求;
掌握利用超类扩展子类的要求;
在程序中相关代码处添加新知识的注释;
删除程序中Person类、PersonTest类,背录删除类的程序代码,在代码录入中理解抽象类与子类的关系和使用特点。
5-4的程序代码为:
package abstractClasses; /** * This program demonstrates abstract classes. * @version 1.01 2004-02-21 * @author Cay Horstmann */ public class PersonTest { public static void main(String[] args) { var people = new Person[2];//超类 // fill the people array with Student and Employee objects people[0] = new Employee("Harry Hacker", 50000, 1989, 10, 1); people[1] = new Student("Maria Morris", "computer science");//子类;将雇员和学生填充到Person引用数组 // print out names and descriptions of all Person objects for (Person p : people) System.out.println(p.getName() + ", " + p.getDescription());//输出对象的姓名和星描述 } }
输出结果截图为:
5-5程序代码为:
package abstractClasses; //定义一个抽象类Person public abstract class Person { public abstract String getDescription(); private String name; public Person(String name) { this.name = name; } public String getName() { return name; } }
输出结果截图为:
5-6程序代码为:
package abstractClasses; import java.time.*;//导入java.time包 public class Employee extends Person { private double salary; private LocalDate hireDay;//构建成员变量 //构造器 public Employee(String name, double salary, int year, int month, int day) { super(name); //使用关键字super调用超类 this.salary = salary;//this:当前对象 hireDay = LocalDate.of(year, month, day); } //域访问器 public double getSalary() { return salary; } public LocalDate getHireDay() { return hireDay; } public String getDescription() { return String.format("an employee with a salary of $%.2f", salary); } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } }
输出结果截图为:
5-7程序代码为:
package abstractClasses; public class Student extends Person { private String major; /** * @param name the student's name * @param major the student's major */ public Student(String name, String major) { // pass name to superclass constructor super(name); this.major = major; } public String getDescription() { return "a student majoring in " + major; } }
输出结果截图为:
删除类的程序为:
package abstractClasses; import java.time.*; public class Employee extends Person { public Employee(String name) { super(name); // TODO Auto-generated constructor stub } private double salary; private LocalDate hireDay; @Override public String getDescription() { // TODO Auto-generated method stub return String.format("an employee with a salary of $%.2f", salary); } @Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return super.clone(); } @Override public boolean equals(Object obj) { // TODO Auto-generated method stub return super.equals(obj); } @Override protected void finalize() throws Throwable { // TODO Auto-generated method stub super.finalize(); } @Override public int hashCode() { // TODO Auto-generated method stub return super.hashCode(); } @Override public String toString() { // TODO Auto-generated method stub return super.toString(); } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public LocalDate getHireDay() { return hireDay; } public void setHireDay(LocalDate hireDay) { this.hireDay = hireDay; } }
同理,在删除类的程序中,关键在于引入@Override,继承相应的父类方法。
(1)观察类的继承层次结构,位于上层的累更具有通用性,甚至更加抽象。
(2)为了提高程序清晰度,包含一个或多个抽象方法的类本身必须被声明为抽象类。除了抽象方法之外,抽象类还可以包含具体数据和具体方法。
(3)抽象方法还充当着占位的角色,他们的具体实现在子类中。
(4)抽象类不能被实例化,既不能创建对象,只能产生子类。可以创建抽象类的对象变量,只是这个变量必须指向它的非抽象子类的对象。
测试程序3:
编辑、编译、调试运行教材程序5-8、5-9、5-10,结合程序运行结果理解程序(教材174页-177页);
掌握Object类的定义及用法;
在程序中相关代码处添加新知识的注释。
5-8程序代码为:
package equals; /** * This program demonstrates the equals method. * @version 1.12 2012-01-26 * @author Cay Horstmann */ public class EqualsTest { public static void main(String[] args) { var alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15);//对alice1进行初始化 var alice2 = alice1;//将alice1的值赋给alice2 var alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15);//对alice3进行初始化 var bob = new Employee("Bob Brandson", 50000, 1989, 10, 1); System.out.println("alice1 == alice2: " + (alice1 == alice2)); System.out.println("alice1 == alice3: " + (alice1 == alice3)); System.out.println("alice1.equals(alice3): " + alice1.equals(alice3)); System.out.println("alice1.equals(bob): " + alice1.equals(bob)); System.out.println("bob.toString(): " + bob); var carl = new Manager("Carl Cracker", 80000, 1987, 12, 15); var boss = new Manager("Carl Cracker", 80000, 1987, 12, 15); boss.setBonus(5000); System.out.println("boss.toString(): " + boss); System.out.println("carl.equals(boss): " + carl.equals(boss)); System.out.println("alice1.hashCode(): " + alice1.hashCode()); System.out.println("alice3.hashCode(): " + alice3.hashCode()); System.out.println("bob.hashCode(): " + bob.hashCode()); System.out.println("carl.hashCode(): " + carl.hashCode()); } }
输出结果截图为:
5-9程序代码为:
package equals; import java.time.*; import java.util.Objects; public class Employee { private String name; private double salary; private LocalDate hireDay; //构建成员变量 public Employee(String name, double salary, int year, int month, int day) { this.name = name; this.salary = salary; hireDay = LocalDate.of(year, month, day); } //域访问器 public String getName()//取得name这个属性的值 { return name; } public double getSalary()//取得Salary这个属性的值 { return salary; } public LocalDate getHireDay() { return hireDay; } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } public boolean equals(Object otherObject) { // a quick test to see if the objects are identical if (this == otherObject) return true;//判断两个引用是否是同一个 // must return false if the explicit parameter is null if (otherObject == null) return false;// // 若参数为空,则返回false // if the classes don't match, they can't be equal if (getClass() != otherObject.getClass()) return false;//getClass():得到对象的类 // now we know otherObject is a non-null Employee var other = (Employee) otherObject; // test whether the fields have identical values return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDay, other.hireDay); } public int hashCode() { return Objects.hash(name, salary, hireDay); } public String toString() { return getClass().getName() + "[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay + "]"; } }
输出结果截图为:
5-10程序代码为:
package equals; public class Manager extends Employee { private double bonus; public Manager(String name, double salary, int year, int month, int day) { super(name, salary, year, month, day); bonus = 0; } public double getSalary() { double baseSalary = super.getSalary(); return baseSalary + bonus; } public void setBonus(double bonus) { this.bonus = bonus; } public boolean equals(Object otherObject) { if (!super.equals(otherObject)) return false; var other = (Manager) otherObject; // super.equals checked that this and other belong to the same classs //检查是否属于同一类 return bonus == other.bonus; } public int hashCode() { return java.util.Objects.hash(super.hashCode(), bonus); } public String toString() { return super.toString() + "[bonus=" + bonus + "]"; } } package equals; public class Manager extends Employee { private double bonus; public Manager(String name, double salary, int year, int month, int day) { super(name, salary, year, month, day); bonus = 0; } public double getSalary() { double baseSalary = super.getSalary(); return baseSalary + bonus; } public void setBonus(double bonus) { this.bonus = bonus; } public boolean equals(Object otherObject) { if (!super.equals(otherObject)) return false; var other = (Manager) otherObject; // super.equals checked that this and other belong to the same classs //检查是否属于同一类 return bonus == other.bonus; } public int hashCode() { return java.util.Objects.hash(super.hashCode(), bonus); } public String toString() { return super.toString() + "[bonus=" + bonus + "]"; } }
输出结果截图为:
Object类的定义及用法:
Object: 所有类的超类,Object是Java所有类的祖先——每一个类都由它开展而来,在不给出超累的情况下,Java会自动把Object作为要定义的超类。
可以使用类型为Object的变量指向任意类型的变量。
实验2:编程练习
定义抽象类Shape:
属性:不可变常量double PI,值为3.14;
方法:public double getPerimeter();public double getArea())。
让Rectangle与Circle继承自Shape类。
编写double sumAllArea方法输出形状数组中的面积和和double sumAllPerimeter方法输出形状数组中的周长和。
main方法中
1)输入整型值n,然后建立个不同的形状。如果输入n,则再输入长和宽。如果输入,则再输入半径。
2) 然后输出所有的形状的周长之和,面积之和。并将所有的形状信息以样例的格式输出。
3) 最后输出每个形状的类型与父类型,使用类似shape.getClass()(获得类型,shape.getClass().getSuperclass()(获得父类型思考sumAllArea和方法放在哪个类中更合适?
3 rect 1 1 rect 2 2 cir 1 输出样例: 18.28 8.14 [Rectangle [width=1, length=1], Rectangle [width=2, length=2], Circle [radius=1]] class Rectangle,class Shape class Rectangle,class Shape class Circle,class Shape
程序代码为:
package ; import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.println("个数"); int a = in.nextInt(); System.out.println("种类"); String rect="rect"; String cir="cir"; Shape[] num=new Shape[a]; for(int i=0;i){ String input=in.next(); if(input.equals(rect)) { System.out.println("长和宽"); int length = in.nextInt(); int width = in.nextInt(); num[i]=new Rectangle(); System.out.println("Rectangle["+"length:"+length+" width:"+width+"]"); } if(input.equals(cir)) { System.out.println("半径"); int radius = in.nextInt(); num[i]=new Circle(); System.out.println("Circle["+"radius:"+radius+"]"); } } Test c=new Test(); System.out.println("求和"); System.out.println(c.sumAllPerimeter(num)); System.out.println(c.sumAllArea(num)); for(Shape s:num) { System.out.println(s.getClass()+","+s.getClass().getSuperclass()); } } public double sumAllArea(Shape score[]) { double sum=0; for(int i=0;i) sum+= score[i].getArea1(); return sum; } public double sumAllPerimeter(Shape score[]) { double sum=0; for(int i=0;i ) sum+= score[i].getPerimeter(); return sum; } }
package; public class Shape { public double getArea11() { // TODO Auto-generated method stub return 0; } public double getPerimeter1() { // TODO Auto-generated method stub return 0; } public double getArea1() { // TODO Auto-generated method stub return 0; } double getArea() { // TODO Auto-generated method stub return 0; } double getPerimeter() { // TODO Auto-generated method stub return 0; } }
老师,我改了好几次程序但还是没有运行出来结果。我下来之后会继续修改程序。
实验总结:(1)上周我们主要学习了继承,还有复习对象与类。学习完继承的好处是所有的子类共有部分可以存放在父类,使得代码可以共享,避免重复,减少出错。
(2)通过课堂测试,我发现了自己平时容易忽略一些细小的知识点,但往往这些知识才更应该引起我们的注意。在实验操作中,也正是由于这字容易被忽略的知识点引起错误,
导致实验结果不能运行出来。
(3)以后我应该更多的将课本上的只是和老师所讲的以及实验课程的内容结合起来,才能够更好的学习,理解所学的知识。