基本上是抄的,只做笔记。
讲在最前面
equals方法必须具备以下特性
自反性(x.equals(x)返回true)、对称性(若x.equals(y)返回true则y.equals(x)返回true)、传递性(若x.equals(y)返回true且y.equals(z)返回true,则x.equals(z)应当返回true)、一致性(若x,y未改变,则反复调用x.equals(y)返回值应当相同)、对任意的非空引用x.equals(null)应返回false。
- 我先开始觉得对称性就是一句废话,我认为理所当然,但是有这么个例子:
e.quals(m) e是Employee的一个对象而m是Manager的一个对象,两者姓名薪水上岗日期均完全相同。若在重写的.equals方法中利用 instanceof 比较类名则会出现问题。
(抄)
网上流行的getClass()版本:
public class Student {
private String name;
public boolean equals(Object object){
if (object == this)
return true;
// 使用getClass()判断对象是否属于该类
if (object == null || object.getClass() != getClass())
return false;
Student student = (Student)object;
return name != null && name.equals(student.name);
}
网上流行的instanceof版本
public class Student {
private String name;
public boolean equals(Object object){
if (object == this)
return true;
// 通过instanceof来判断对象是否属于类
if (object == null || !(object instanceof Student))
return false;
Student student = (Student)object;
return name!=null && name.equals(student.name);
}
}
事实上两种方案都是有效的,区别就是getClass()限制了对象只能是同一个类,而instanceof却允许对象是同一个类或其子类。我要说的其实不是这个,你再看看下面这个instanceof 版本
public class Student {
####private String name;
public boolean equals(Object object){
if (object == this)
return true;
// 通过instanceof来判断对象是否属于类
if (object == null || !(object instanceof Student))
return false;
Student student = (Student)object;
// 跟上个instanceof版本唯一不同的是,这里使用student.getName()而不是student.name
return name!=null && name.equals(student.getName());
}
}
你会发现,如果将name.equals(student.name);改为name.equals(student.getName());或getName().equals(student.getName());都不规范。原因:
假设GoodStudent extends Student。
Student student=new Student();
GoodStudent goodstudent=new GoodStudent();
student.setName("some");
goodstudent.setName("some");
-
重写方法尾行采用name.equals(student.getName()):
调用方法goodstudent.equals(student)返回false
调用方法student.equals(goodstudent)返回true -
重写方法尾行采用 getName().equals(student.name)
调用方法goodstudent.equals(student))返回true
调用方法student.equals(goodstudent))返回false -
重写方法尾行采用name.equals(student.name)
反正还是有问题。
因为name是private修饰的。参数goodstudent是GoodStudent类,而当main方法在父类中进行时,假如equals的调用者是Student类,而参数student如果是GoodStudent类,由于name属性对其它类不可见,不论是否有值,student.name为null,所以equals返回false。
你只能在尾行书写:
getName().equals(student.getName());
这样equals方法就变成了父类与子类也可进行equals操作了,只要name属性的值一样。按照各自的业务可以有各自的equals实现,但是按照规范来说,equals不应该是父类与子类对象可以进行的操作,所以重写equals方法应当选用getClass()来进行判断对象是否属于类,而不应该用instanceof,后者会让子类钻漏洞。
- Object.equals(==):比较内存地址;基本数据类型(储存在栈中)用它比较就行。
特别要说的是,关于字符串。
如果你写:
String a1="abc";
String b1="abc";
a1==b1返回true。
但是如果你写:
String a2=new String("abc");
String b2=new String("abc");
a2==b2将返回false。
- String.equals: 比较内容即可,不管内存地址。
也就是说,a2.equals(b2)返回true。
总结:
Object.equals相等,String.equals一定相等;
String.equals相等,Object.equals不一定相等。
需要格外强调的是,你比较类的时候,虚拟机知道你传的参是object(类)类,所以会自行调用Object.equals的比较法。也就是说比较地址。所以使用时建议重写。
但是!重写.equals必须重写hashcode!
我还是没懂。
nstanceof进行类型检查规则是:你属于该类吗?或者你属于该类的派生类吗?而通过getClass获得类型信息采用==来进行检查是否相等的操作是严格的判断。不会存在继承方面的考虑
大概就是father1 instanceof father T
child instanceif father T
但是
child.getClass()==father1.getClass() F
网友评论