4.3 jmu-Java-03面向对象-06-继承覆盖综合练习-Person、Student、Employee、Company (20 分)
定义Person抽象类,Student类、Company类,Employee类。
Person类的属性: String name, int age, boolean gender
Person类的方法:
public Person(String name, int age, boolean gender);
public String toString(); //返回"name-age-gender"格式的字符串
public boolean equals(Object obj);//比较name、age、gender,都相同返回true,否则返回false
Student类继承自Person
,属性:String stuNo, String clazz
Student类的方法:
//建议使用super复用Person类的相关有参构造函数
public Student(String name, int age, boolean gender, String stuNo, String clazz);
public String toString(); //返回 “Student:person的toString-stuNo-clazz”格式的字符串
public boolean equals(Object obj);//首先调用父类的equals方法,如果返回true,则继续比较stuNo与clazz。
Company类属性:String name
Company类方法:
public Company(String name);
public String toString(); //直接返回name
public boolean equals(Object obj);//name相同返回true
Employee类继承自Person
,属性:Company company, double salary
Employee类方法:
//建议使用super复用Person类的相关有参构造函数
public Employee(String name, int age, boolean gender, double salary, Company company);
public String toString(); //返回"Employee:person的toString-company-salary"格式的字符串
public boolean equals(Object obj);//首先调用父类的equals方法,如果返回true。再比较company与salary。
//比较salary属性时,使用DecimalFormat df = new DecimalFormat("#.#");保留1位小数
编写equals方法重要说明:
- 对Employee的company属性的比较。要考虑传入为null的情况。如果company不为null且传入为null,返回false
- 对所有String字符类型比较时,也要考虑null情况。
提示
- 排序可使用Collections.sort
- equals方法要考虑周全
main方法说明
- 创建若干Student对象、Employee对象。
输入s,然后依次输入name age gender stuNo clazz创建Student对象。
输入e,然后依次输入name age gender salary company创建Employee对象。
然后将创建好的对象放入List personList。输入其他字符,则结束创建。
创建说明: 对于String类型,如果为null则不创建对象,而赋值为null。对于company属性,如果为null则赋值为null,否则创建相应的Company对象。
-
对personList中的元素实现先按照姓名升序排序,姓名相同再按照年龄升序排序。提示:可使用Comparable或Comparator
-
接受输入,如果输入为exit则return退出程序,否则继续下面步骤。
-
将personList中的元素按照类型分别放到stuList与empList。注意:不要将两个内容相同的对象放入列表(是否相同是根据equals返回结果进行判定)。
-
输出字符串stuList,然后输出stuList中的每个对象。
-
输出字符串empList,然后输出empList中的每个对象。
1-3
为一个测试点 4-6
为一个测试点
输入样例:
s zhang 23 false 001 net15
e wang 18 true 3000.51 IBM
s zhang 23 false 001 net15
e bo 25 true 5000.51 IBM
e bo 25 true 5000.52 IBM
e bo 18 true 5000.54 IBM
e tan 25 true 5000.56 IBM
e tan 25 true 5000.51 IBM
s wang 17 false 002 null
s wang 17 false 002 null
e hua 16 false 1000 null
s wang 17 false 002 net16
e hua 16 false 1000 null
e hua 18 false 1234 MicroSoft
!
continue
输出样例:
Employee:bo-18-true-IBM-5000.54
Employee:bo-25-true-IBM-5000.51
Employee:bo-25-true-IBM-5000.52
Employee:hua-16-false-null-1000.0
Employee:hua-16-false-null-1000.0
Employee:hua-18-false-MicroSoft-1234.0
Employee:tan-25-true-IBM-5000.56
Employee:tan-25-true-IBM-5000.51
Student:wang-17-false-002-null
Student:wang-17-false-002-null
Student:wang-17-false-002-net16
Employee:wang-18-true-IBM-3000.51
Student:zhang-23-false-001-net15
Student:zhang-23-false-001-net15
stuList
Student:wang-17-false-002-null
Student:wang-17-false-002-net16
Student:zhang-23-false-001-net15
empList
Employee:bo-18-true-IBM-5000.54
Employee:bo-25-true-IBM-5000.51
Employee:hua-16-false-null-1000.0
Employee:hua-18-false-MicroSoft-1234.0
Employee:tan-25-true-IBM-5000.56
Employee:tan-25-true-IBM-5000.51
Employee:wang-18-true-IBM-3000.51
我的代码:
- 用到的各种类
import java.util.Scanner;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Collections;
- 写Person类中比较重要的一个点是用到了接口。
implements
是类去实现一个接口会用到的一个语句,Comparable<Person>
是接口本身的定义,这是一个作为比较器的接口,传入的是<Person>
类。需要做到的点是要在本类中将compareTo
函数具体实现。 - 关于
compareTo
函数,一般我们会用1
表示当前值大于传入值;-1
表示当前值小于传入值;0
表示当前值等于传入值;如果需要对类的多个属性进行比较的话,可以在这个分支再次进行拓展。
class Person implements Comparable<Person>{
private String name;
private int age;
private boolean gender;
public Person(String name, int age, boolean gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
@Override
public String toString() {
return name + "-" + age + "-" + gender;
}
@Override
public int hashCode() {
return Objects.hash(age, gender, name);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
return age == other.age && gender == other.gender && Objects.equals(name, other.name);
}
@Override
public int compareTo(Person o) {
int x = this.name.compareTo(o.name);
if(x!=0) {
return x;
}
else {
if(this.age>o.age)
return 1;
else if (this.age<o.age)
return -1;
else
return 0;
}
}
}
class Student extends Person {
private String stuNo;
private String clazz;
public Student(String name, int age, boolean gender, String stuNo, String clazz) {
super(name, age, gender);
this.stuNo = stuNo;
this.clazz = clazz;
}
@Override
public String toString() {
return "Student:" + super.toString()+ "-" + stuNo + "-" + clazz;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + Objects.hash(clazz, stuNo);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
return Objects.equals(clazz, other.clazz) && Objects.equals(stuNo, other.stuNo);
}
}
class Company{
private String name;
public Company(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
@Override
public int hashCode() {
return Objects.hash(name);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Company other = (Company) obj;
return Objects.equals(name, other.name);
}
}
- 在Employee类中学习到在编写equals函数的时候,当我们要去比较浮点数的大小的时候,我们可以使用
DecimalFormat
类去新建一种浮点数的标准格式(以字符串的形式确定下来),然后直接去比较这种确定下来的形式,避免由于浮点误差而产生的误判。
class Employee extends Person{
private Company company;
private double salary;
public Employee(String name, int age, boolean gender, Company company, double salary) {
super(name, age, gender);
this.company = company;
this.salary = salary;
}
@Override
public String toString() {
return "Employee:"+ super.toString()+ "-" + company + "-" + salary;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + Objects.hash(company, salary);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
DecimalFormat df = new DecimalFormat("#.#");//创建一个Decimal的格式
return Objects.equals(company, other.company)
&& (df.format(salary)).equals(df.format(other.salary));
}
}
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
List<Person> personList = new ArrayList<>();
List<Person> stuList = new ArrayList<>();
List<Person> empList = new ArrayList<>();
String choice;
while(sc.hasNext())
{
choice = sc.next();
if(choice.equals("s")) {
String name = sc.next();
if(name.equals("null"))
{
name = null;
}
int age = sc.nextInt();
boolean gender = sc.nextBoolean();
String stuNo = sc.next();
if(stuNo.equals("null"))
{
stuNo = null;
}
String clazz = sc.next();
if(clazz.equals("null"))
{
clazz = null;
}
Person student = new Student(name,age,gender,stuNo,clazz);
personList.add(student);
//
if(!stuList.contains(student)) {
stuList.add(student);
}
}
else if(choice.equals("e")) {
String _name = sc.next();
if(_name.equals("null"))
{
_name = null;
}
int _age = sc.nextInt();
boolean _gender = sc.nextBoolean();
double salary = sc.nextDouble();
String company_name = sc.next();
Company company;
if(company_name.equals("null"))
{
company = null;
}
else
{
company = new Company(company_name);
}
Person employee = new Employee(_name,_age,_gender,company,salary);
personList.add(employee);
//
if(!empList.contains(employee)) {
empList.add(employee);
}
}
else break;
}
//output
Collections.sort(personList);
for (Person person : personList) {
System.out.println(person.toString());
}
if(sc.next().equals("exit")) {
sc.close();
return ;
}
//
Collections.sort(stuList);
System.out.println("stuList");
for (Person person : stuList) {
System.out.println(person.toString());
}
//
Collections.sort(empList);
System.out.println("empList");
for (Person person : empList) {
System.out.println(person.toString());
}
sc.close();
}
}
- 在主函数中主要学到的以下的一些零散的知识:
- 进行流程控制未必一定都是
switch-case
结构比较好,一些情况下级联的if-else if
结构也很不错,因为在前者中,通常break
语句只能跳出switch-case
结构中的某个case
,而没有办法直接跳出循环,但是后者却可以。 - 注意到当我们要对许多个类进行某种排序的时候,单纯使用数据结构自带的
sort
很多时候并不能达到我们想要的效果,所以这些情况下,就需要我们自己去给类加上想要用于比较的比较器接口自己去实现它的比较函数。 - 在对LIst中的多个类进行sort的时候,可以多多关注
Collections.sort
。
- 进行流程控制未必一定都是
题外话:
- 关于
equals
方法的重构:- 首先我们一般比较
传入的obj
是否于我们当前的类是同一个引用 - 其次我们一般还会比较
传入的obj
是否是一个null
- 如果需要比较的本类是子类,我们会额外先去比较它与传入的类是不是有共同的父类。(用super调用父类的equals)
- 接下来是比较当前的两个类的类名是不是相同的。
- 在接下来会新建一个本类的实例去存储传入的类,为后续逐一比较两个类的属性做铺垫。
- return部分一般直接取两个类逐一属性的比较的逻辑结果的总合取的结果。
- 首先我们一般比较