实验六 继承定义与使用
1、实验目的与要求
(1) 理解继承的定义;
(2) 掌握子类的定义要求
(3) 掌握多态性的概念及用法;
(4) 掌握抽象类的定义及用途;
(5) 掌握类中4个成员访问权限修饰符的用途;
(6) 掌握抽象类的定义方法及用途;
(7)掌握Object类的用途及常用API;
(8) 掌握ArrayList类的定义方法及用法;
(9) 掌握枚举类定义方法及用途。
一、 理论学习部分目的与要求
5.1 类、超类和子类
1、父类/子类是相对的;
2、继承:用已有类来构建新类的一种机制;
3、继承层次结构中,每 个子类对象也可视作 是超类对象,因此, 可以将子类对象赋给 超类变量。
4、动态绑定和静态绑定 。
5、阻止继承:final类和方法
6、强制类型转换:如果要把一个超类对象赋给一个子类对象变量,就必须进 行强制类型转换。
7、受保护访问:如果希望超类的某些方法或域允许被子类访问,就需要在 超类定义时,将这些方法或域声明为protected 。
5.2 Object:所有类的超类
1、Object类是Java中所有类的祖先——每一个类都由它扩 展而来。在不给出超类的情况下,Java会自动把Object 作为要定义类的超类。
2、equals方法、hashCode方法、toString方法
5.3 泛型数组列表
1、Java中,利用ArrayList类,可允许程序在运行 时确定数组的大小(没有<>的ArrayList将被认为是一个删去了类型 参数的“原始”类型)
2、a.ArrayList定义
b.添加新元素
c.统计个数
d.调整大小
e.访问
f.增加与删除
5.4 对象包装器和自动打包
所有基本数据类型都有着与之对应的预定义类,它们被称 为对象包装器(wrapper)。
2、以下前6个对象包装器类都是从公共包装器类Number继承 而来。 Integer Long Float Double Short Byte Character Void Boolean
3、打包和拆包是编译器认可的。
5.5 参数数量可变的方法
用户自己可以定义可变参数的方法,并将参数指 定为任意类型,甚至是基本类型。
5.6 枚举类
1、声明枚举类
2、为枚举类增加构造函数
3、Enum类的API
5.7 继承设计的技巧
① 将公共操作和域放在超类。 ② 不要使用受保护的域。 ③ 使用继承实现“is-a”关系。 ④ 除非所有继承的方法都有意义,否则就不要 使用继承。 ⑤ 在覆盖方法时,不要改变预期的行为。 ⑥ 使用多态,而非类型信息。 ⑦ 不要过多地使用反射。
2、实验内容和步骤
实验1: 导入第5章示例程序,测试并进行代码注释
测试程序1:
? 在elipse IDE中编辑、调试、运行程序5-1 (教材152页-153页) ;
? 掌握子类的定义及用法;
结合程序运行结果,理解并总结OO风格程序构造特点,理解Employee和Manager类的关系子类的用途,并在代码中添加注释
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 Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15);//Manager类定义类对象boss boss.setBonus(5000);//更改器更改 Employee[] staff = new Employee[3];//生成雇员对象 // fill the staff array with Manager and Employee objects用Manager和Employee对象人员子类填充员工数组 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()); } }
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); }//构造器构造Employee对象 public String getName() { return name; }//访问器 public double getSalary() { return salary; } public LocalDate getHireDay() { return hireDay; } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } }
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();//用父类的getSalary获得的 return baseSalary + bonus; } public void setBonus(double b)//更改器 { bonus = b; } }
及结果:
测试程序2:
? 编辑、编译、调试运行教材PersonTest程序(教材163页-165页);
掌握超类的定义及其使用要求;
? 掌握利用超类扩展子类的要求;
在程序中相关代码处添加新知识的注释。
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) { Person[] people = new Person[2];//定义一个Person对象数组 // 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"); // print out names and descriptions of all Person objects输出姓名和描述人员信息 for (Person p : people) System.out.println(p.getName() + ", " + p.getDescription());//定义了getDescription方法 } }
package abstractClasses; public abstract class Person { public abstract String getDescription();//abstract抽象方法 private String name; public Person(String name)//定义属性 { this.name = name;//调用构造器构造参数 } public String getName()//访问器 { return name; } }
package abstractClasses; public abstract class Person { public abstract String getDescription();//abstract抽象方法 private String name; public Person(String name)//定义name属性 { this.name = name;//调用构造器构造参数 } public String getName()//访问器 { return name; } }
package abstractClasses; import java.time.*; public class Employee extends Person//扩展了Employee类 { private double salary;//定义属性 private LocalDate hireDay; //构造Employee类 public Employee(String name, double salary, int year, int month, int day) { super(name); this.salary = salary; hireDay = LocalDate.of(year, month, day); } //访问Salary属性; 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; } }
package abstractClasses; public class Student extends Person//扩展了 Student类 { private String major; /** * @param nama the student‘s name * @param major the student‘s major */ public Student(String name, String major) { // pass n to superclass constructor将n传递给超类构造函数 super(name);//父类构造器super this.major = major; } public String getDescription() { return "a student majoring in " + major; }//访问器 }
测试程序3:
1、编辑、编译、调试运行教材程序5-8、5-9、5-10,结合程序运行结果理解程序(教材174页-177页);
2、掌握Object类的定义及用法;
3、 在程序中相关代码处添加新知识的注释。
Equals:
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)//定义方法 { Employee alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15); Employee alice2 = alice1; Employee alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15); Employee 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); Manager carl = new Manager("Carl Cracker", 80000, 1987, 12, 15); Manager 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()); } }
Employee.java:
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;//this调用 hireDay = LocalDate.of(year, month, day); } //返回一个代表该对象域值的字符串 public String getName() { return name; } public double getSalary() { 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; // if the classes don‘t match, they can‘t be equal if (getClass() != otherObject.getClass()) return false; // now we know otherObject is a non-null Employee Employee 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); } //调用超类的toString方法 public String toString() { return getClass().getName() + "[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay + "]"; } }
Manger.java:
package equals; //定义Manger方法 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;//this的调用 } public boolean equals(Object otherObject)//比较两个对象是否相等 { if (!super.equals(otherObject)) return false; Manager other = (Manager) otherObject; // super.equals checked that this and other belong to the same class return bonus == other.bonus; } public int hashCode() { return java.util.Objects.hash(super.hashCode(), bonus); }//返回对象的散列码 public String toString() { return super.toString() + "[bonus=" + bonus + "]"; }//返回描述该对象值的字符串 }
结果如下:
测试程序4:
? 在elipse IDE中调试运行程序5-11(教材182页),结合程序运行结果理解程序;
? 掌握ArrayList类的定义及用法;
在程序中相关代码处添加新知识的注释。
package arrayList; import java.util.*; import equals.Employee; /** * This program demonstrates the ArrayList class. * @version 1.11 2012-01-26 * @author Cay Horstmann */ public class ArrayListTest { public static void main(String[] args) { // fill the staff array list with three Employee objects ArrayList<Employee> staff = new ArrayList<>(); //用add方法为数组添加新元素 staff.add(new Employee("Carl Cracker", 75000, 1987, 12, 15)); staff.add(new Employee("Harry Hacker", 50000, 1989, 10, 1)); staff.add(new Employee("Tony Tester", 40000, 1990, 3, 15)); // raise everyone‘s salary by 5% for (Employee e : staff) e.raiseSalary(5); // print out information about all Employee objects for (Employee e : staff) System.out.println("name=" + e.getName() + ",salary=" + e.getSalary() + ",hireDay=" + e.getHireDay()); }//循环数组 }
结果如下:
测试程序5:
1、 编辑、编译、调试运行程序5-12(教材189页),结合运行结果理解程序;
2、 掌握枚举类的定义及用法;
在程序中相关代码处添加新知识的注释。
package enums; import java.util.*; /** * This program demonstrates enumerated types. * @version 1.0 2004-05-24 * @author Cay Horstmann */ public class EnumTest { public static void main(String[] args) { //构造枚举常数 Scanner in = new Scanner(System.in); System.out.print("Enter a size: (SMALL, MEDIUM, LARGE, EXTRA_LARGE) "); String input = in.next().toUpperCase(); Size size = Enum.valueOf(Size.class, input);//静态方法valueOf System.out.println("size=" + size); System.out.println("abbreviation=" + size.getAbbreviation()); if (size == Size.EXTRA_LARGE) System.out.println("Good job--you paid attention to the _."); } } //声明定义类型是一个类 enum Size { SMALL("S"), MEDIUM("M"), LARGE("L"), EXTRA_LARGE("XL"); //构造器 private Size(String abbreviation) { this.abbreviation = abbreviation; } public String getAbbreviation() { return abbreviation; } private String abbreviation;//返回枚举常量名 }
结果如下:
实验2:编程练习1
定义抽象类Shape:
属性:不可变常量double PI,值为3.14;
方法:public double getPerimeter();public double getArea())。
让Rectangle与Circle继承自Shape类。
编写double sumAllArea方法输出形状数组中的面积和和double sumAllPerimeter方法输出形状数组中的周长和。
main方法中
1)输入整型值n,然后建立n个不同的形状。如果输入rect,则再输入长和宽。如果输入cir,则再输入半径。
2) 然后输出所有的形状的周长之和,面积之和。并将所有的形状信息以样例的格式输出。
3) 最后输出每个形状的类型与父类型,使用类似shape.getClass()(获得类型),shape.getClass().getSuperclass()(获得父类型);
思考sumAllArea和sumAllPerimeter方法放在哪个类中更合适?
输入样例:
输出样例:
package TEST; import TEST.Shape; import TEST.Rectangle; import TEST.Circle; import java.math.*; import java.util.Scanner; public class demo { public static void main(String[] args) { Scanner in=new Scanner(System.in); System.out.println(); int n=in.nextInt(); String rect="rect"; String cir="cir"; Shape [] a=new Shape[n]; for(int i=0;i<n;i++) { String read=in.next(); if(read.equals(rect)) { int length=in.nextInt(); int width=in.nextInt(); a[i]=new Rectangle(width,length); } if(read.equals(cir)) { int radius=in.nextInt(); a[i]=new Circle(radius); } } for(int i=0;i<n;i++) { System.out.println(a[i]); } demo b=new demo(); System.out.println(b.sumAllPerimeter(a)); System.out.println(b.sumAllArea(a)); for(Shape s:a) { System.out.println(s.getClass()+","+s.getClass().getSuperclass()); } } public double sumAllArea(Shape a[]) { double sum=0; for(int i=0;i<a.length;i++) sum=sum+a[i].getArea(); return sum; } public double sumAllPerimeter(Shape a[]) { double sum=0; for(int i=0;i<a.length;i++) sum=sum+a[i].getPerimeter(); return sum; } }
public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.println("请输入创建图形的个数"); int a = in.nextInt(); System.out.println("请输入图形种类(选择输入cir或rect)"); String rect="rect"; String cir="cir"; Shape[] num=new Shape[a]; for(int i=0;i<a;i++){ String input=in.next(); if(input.equals(rect)) { System.out.println("请输入长和宽"); int width = in.nextInt(); int length = in.nextInt(); num[i]=new 长方形(width,length); System.out.println("长方形["+"长方形的长为:"+length+" 长方形的宽为:"+width+"]"); } if(input.equals(cir)) { System.out.println("输入所创建的圆的半径"); int r = in.nextInt(); num[i]=new 圆形(r); System.out.println("圆["+"圆的半径为:"+r+"]"); } } cirec c=new cirec(); System.out.println("求所有图形的面积和:"); System.out.println(c.AllPerimeter(num)); System.out.println("求所有图形的周长和:"); System.out.println(c.AllArea(num)); for(Shape s:num) { System.out.println(s.getClass()+","+s.getClass().getSuperclass()); } } } package 两个图形的; abstract class Shape { abstract double getPerimeter(); abstract double getArea(); } class 圆形extends Shape{ private double PI=3.14; private int r; public 圆形(int r) { this.r = r; } double getPerimeter(){ return 2 * PI * r; } double getArea(){ return r * r*PI; } } class 长方形extends Shape{ private int width; private int length; public 长方形(int length, int width) { this.width = width; this.length = length; } double getPerimeter(){ return 2*(length+width); } double getArea(){ return length*width; } }
结果:
实验3: 编程练习2
编制一个程序,将身份证号.txt 中的信息读入到内存中,输入一个身份证号或姓名,查询显示查询对象的姓名、身份证号、年龄、性别和出生地
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Scanner; public class ID { public static People findPeopleByname(String name) { People flag = null; for (People people : peoplelist) { if(people.getName().equals(name)) { flag = people; } } return flag; } public static People findPeopleByid(String id) { People flag = null; for (People people : peoplelist) { if(people.getnumber().equals(id)) { flag = people; } } return flag; } private static ArrayList<People> peoplelist; public static void main(String[] args) { peoplelist = new ArrayList<People>(); Scanner scanner = new Scanner(System.in); File file = new File("D:\\java\\1\\身份证号.txt"); try { FileInputStream files = new FileInputStream(file); BufferedReader in = new BufferedReader(new InputStreamReader(files)); String temp = null; while ((temp = in.readLine()) != null) { Scanner linescanner = new Scanner(temp); linescanner.useDelimiter(" "); String name = linescanner.next(); String number = linescanner.next(); String sex = linescanner.next(); String age = linescanner.next(); String place = linescanner.nextLine(); People people = new People(); people.setName(name); people.setnumber(number); people.setage(age); people.setsex(sex); people.setaddress(address); peoplelist.add(people); } } catch (FileNotFoundException e) { System.out.println("文件未找到"); e.printStackTrace(); } catch (IOException e) { System.out.println("文件读取错误"); e.printStackTrace(); } boolean isTrue = true; while (isTrue) { System.out.println("***********"); System.out.println("1.按姓名查询"); System.out.println("2.按身份证号查询"); System.out.println("3.退出"); System.out.println("***********"); int nextInt = scanner.nextInt(); switch (nextInt) { case 1: System.out.println("请输入姓名:"); String peoplename = scanner.next(); People people = findPeopleByname(peoplename); if (people != null) { System.out.println(" 姓名:"+ people.getName() + " 身份证号:"+ people.getnumber() + " 年龄:"+ people.getage()+ " 性别:"+ people.getsex()+ " 地址:"+ people.getadress() ); } else { System.out.println("不存在此人"); } break; case 2: System.out.println("请输入身份证号:"); String peopleid = scanner.next(); People people1 = findPeopleByid(peopleid); if (people1 != null) { System.out.println(" 姓名:"+ people1.getName()+ " 身份证号:"+ people1.getnumber()+ " 年龄:"+ people1.getage()+ " 性别:"+ people1.getsex()+ " 地址:"+ people1.getplace()); } else { System.out.println("不存在此人"); } break; case 3: isTrue = false; System.out.println("byebye!"); break; default: System.out.println("输入有误"); } } }}
结果如下:
总结:通过本章继承的学习 ,我明白了to string、子类、超类、枚举类等理论知识,因为国庆出去一趟,也没怎么看书,回来后草草的完成了作业,实验部分自己动手呢能力不是很强,还得努力学习。
原文地址:https://www.cnblogs.com/YRQY/p/9724652.html