Effective Java读书笔记、感悟——2.1对所有对象都通用的方法之equals

一:覆盖equals时请遵守通用约定

一直觉着equals挺实用也很简单,今天发现我大错特错了,包括以前的代码存在着很大的问题,以后使用equals必须要谨慎对待,因为此处带来的问题会。

1. 关于原则:

à不保证equals传入的是与自己相同的类的对象,一定要保证两个对象的equals返回相同的值,因此我们平时编程的时候才可以从不关注equals的参数是哪个。

à要保证传递性,比如子类的equals一定保证能正确的输出与父类对象比对的结果。且equal相互传递。可以考虑的实现比如抽象父类,复合优先于继承。

àequals比较不可依赖不可靠的资源。如IP地址,Android中sdcard中的配置文件,web services上的某些信息。

à通过每次操作都使用instanceof过滤保证不会equals(null)返回true。

2. 关于经验:

à使用==操作符检查“参数是否为这个对象的引用”。

à使用instanceof操作符检查“参数是否为正确类型”。

à把参数转换成正确的类型。

à对于该类中的每个“关键(significant)”域,检查参数中的域是否与该对象中对应的域相匹配。

à当你编写完一个equals方法后,应该问自己三个问题:它是否是对称的、传递的、一致的?

3. 同时还有几个告诫:

à覆盖equals方法总要覆盖hashCode;

à不要企图让equals方法过于智能;

à不要将equals声明中的Object对象替换为其他的类型(最好加上@Override来确保覆盖)。

因为这个部分跟以前的认识出入很大,这里举个例子来修改一下实现。

从csdn上找到一个例子,这里不给出链接了,并不是为了批判。博主的访问量很多,也只是为了说明equal的用法,这可能可以更好的说明现在很多认识与我一样略有小菜成分。这里如果只是简单的理解equals会遇到很多问题,这里先看代码:

Java代码 复制代码 收藏代码
  1. public class Person{
  2. private String name;
  3. private int age;
  4. public Person(String name,int age){
  5. this.name=name;
  6. this.age=age;
  7. }
  8. public boolean equals(Object obj){
  9. Person per1=this;
  10. Person per2=(Person) obj;
  11. boolean flag=false;
  12. if(per1.name.equals(per2.name)&&per1.age==per2.age){
  13. flag=true;
  14. }
  15. return flag;
  16. }
  17. public String toString(){
  18. return "姓名:"+name+"/t年龄:"+age;
  19. }
  20. }
  21. public class TestEquals{
  22. public static void main(String[] args){
  23. Person p1=new Person("c++",30);
  24. Person p2=new Person("Java",15);
  25. System.out.println(p1);
  26. System.out.println(p2);
  27. String out=p1.equals("sdff") ? "p1和p2是同一个人":"p1和p2不是同一个人";
  28. System.out.println(out);
  29. }
  30. }
public class Person{	private String name;	private int age;	 	public Person(String name,int age){		this.name=name;		this.age=age;	}	public boolean equals(Object obj){		Person per1=this;		Person per2=(Person) obj;		boolean flag=false;		  		if(per1.name.equals(per2.name)&&per1.age==per2.age){			flag=true;		} 		return flag;	 } 	 public String toString(){		 return "姓名:"+name+"/t年龄:"+age;	}}public class TestEquals{	 public static void main(String[] args){		 Person p1=new Person("c++",30);		 Person p2=new Person("Java",15);		 System.out.println(p1);		 System.out.println(p2);		 String out=p1.equals("sdff") ? "p1和p2是同一个人":"p1和p2不是同一个人";		 System.out.println(out);	 }}

不涉及代码效率和编码习惯的问题,通过刚才提到的很容易发现其中的问题,很明显传入不同类型的obj程序就会报错java.lang.ClassCastException;传入null报错NullPointer。如果我们要添加一个子类Worker,存在一个workid,首先直观的实现方法:

Java代码 复制代码 收藏代码
  1. public boolean equals(Object obj){
  2. boolean flag=false;
  3. if(obj instanceof Worker){
  4. if(super.equals(obj)){
  5. Worker worker = (Worker)obj;
  6. if(worker.workid==workid){
  7. flag = true;
  8. }
  9. }
  10. }
  11. return flag;
  12. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值