在类中equals()方法中使用instanceof出现的问题
前面我们对于equals()和==的区别进行了一个探究。在这个复习类的使用的时候我发现了一个关于instanceof的容易犯错的点,好让我们现在来看一段代码。
我们先定义一个Employee类:这里主要看类中
查看代码
public class Employee extends Person{
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 void raiseSalary(Double byPercent){
double raise = salary *byPercent / 100;
salary += raise;
}
@Override
public String getDescription() {
return "a employee wit a salary of " + this.salary;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Employee)) return false;
Employee other = (Employee) o;
return salary == other.salary;
}
@Override
public int hashCode() {
return Objects.hash(name, salary, hireDay);
}
}
这里我们在定义一个Employee的子类Manager:
查看代码
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;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Manager)) return false;
if (o == null || getClass() != o.getClass()) return false;
Manager manager = (Manager) o;
return bonus == manager.bonus;
}
}
在测试类我们分别生成Manager类和Employee类:
Manager m = new Manager("Jack", 50000, 1999, 12, 25);
Employee e = new Employee("Jack", 50000, 1999, 12, 25);
System.out.println(e.equals(m));//true
System.out.println(m.equals(e));//false
这时我们发现这不符合equals()方法的一致性,因此使用instanceof来判断是否是相同的类型是存在一定的问题的。好现在让我们来了解一下instanceof关键字的原理,根据jvm对于instanceof关键字的规范,我们将instanceof的伪代码写出来:
查看代码
//obj instantceof T
if (obj == null){
return false;
}else{
try {
T temp = (T) obj;
return true;
}catch (ClassCastException e){
return false;
}
}
上面的代码的意思就是当obj为null时返回false,当obj可以转换成T类型不会出现异常时返回true。
对于S instanceof T,我对于S不同的三中类型都进行了判断和验证:
查看代码
//第一种情况S为普通类
Employee s = new Employee();
Manager s1 = new Manager("jack", 343.5, 1998, 3, 2);
Cat s3 = new Cat();
System.out.println(s instanceof Employee );//s是Employee类 true
System.out.println(s1 instanceof Employee);//s1是Employee的子类 true
//System.out.println(s3 instanceof Employee);//不兼容的类型: demo0.Cat无法转换为demo0.Employee
System.out.println(s instanceof Cloneable);//s实现了Cloneable true
//第二种情况S为接口类
IntConsumer s4 = new IntConsumer() {
@Override
public void accept(int value) {
}
};
System.out.println(s4 instanceof Object);//true
//第三种情况S为数组
int[] list = new int[19];
System.out.println(list instanceof Object);//true
好我们现在回来看之前的那个出现问题的代码:
Manager m = new Manager("Jack", 50000, 1999, 12, 25);
Employee e = new Employee("Jack", 50000, 1999, 12, 25);
System.out.println(e.equals(m));//true
System.out.println(m.equals(e));//false
对于m.equals(e)的返回值为false,通过我们上面的分析我们可以知道,在equals中我们是用instanceof进行判断的,在判断中我们会将Employee转成Manager这时就发生了异常,在java中会自动的帮我们向上转型但是我们不会轻易的向下转型。所以下次我们覆写类中的equals()方法时我们尽量不用instanceof关键字对对象进行判断。
posted on 2022-03-27 14:45 vernier_caliper 阅读(52) 评论(0) 收藏 举报
浙公网安备 33010602011771号