Java通用方法

Object中的所有非final方法(equals 、hashCode、toString、clone 和 finalize ) 目的是为了Override而设计的

Equals不需要重写的几种情况:
1 一个类的每个实例本质上都是惟一的。对于代表了活动实体而不是值(value)的类比如Thread。

2 不关心一个类是否提供了"逻辑相等(logical equality)"测试功能。例如java.util.Random改写equals方法,他检查两个Random实例是否产生相同的随机数序列,但是设计者并不认为客户会需要这样的功能,在这样的情况下,从Object继承的equals实现已经足够了。

3 超类 已经改写了equals方法,从超类继承过来的子类也是合适的。例如大多数的Set从AbstractSet继承了equals实现,List实现从AbstractList继承了equals实现,Map实现从AbstractMap继承了equals实现

4 一个类是私有的,或者是包级私有的 ,并且可以确定他的equals方法永远不会被调用。
 public boolean  equals(Object o)  {
throw new UnsupportedOperationException();
}

什么时候改写Object.equals?
当 一个类有自己特有的“逻辑相等”概念(不同于对象身份的概念),而且超类也没有改写equals以实现期望的行为。
改写equals的目的:比较两个指向值对象的引用时候,希望知道他们逻辑上是否相等,而并不是他们是否指向同一对象。

重写equals方法的通用约定:
1 . 自反性 对于任意的引用值X,X.equals(X)一定为true
2. 对称性 对于任意的引用值X,Y 当且仅当Y.equals(X)返回true时,X.equals(Y)也一定返回true。
3. 传递性 对于任意的引用值X,Y,Z 如果X.equals(Y)返回true,并且Y.equals(Z)也返回true时,那么X.equals(Z)也一定要返回true
4. 一致性 对于任意的引用值X和Y,如果用于equals比较的对象信息没有被修改的话,那么,多次调用X.equals(Y)要么一致的返回true要么一致的返回false。
5. 对于任意的非空引用值X,X.equals(null)一定返回false

对称性:
例如:
Public   final class  CaseInsensitveString  {
private final String s ;
public CaseInsensitveString (String s){
if(s==null) throw new NullPointerException();
this.s=s;
}
@override public boolean equals(Object o) {
if(o instance of CaseInsensitveString )
return s.equalsIgnore(((CaseInsensitveString)o).s);
if(o instanceof String)
return s.equalsIgnoreCase((String)o);
retrun false;
}

}

假设一个不区分大小写的字符串和一个普通的字符串
CaseInsensitveString cis =new CaseInsensitveString ("Polish");
String p ="polish";
这时 cis.equals(p)返回true 但是在String类中equals却不知道区分大小写的字符串所以s.equals(p)却返回了false,违反了对称性。
所以可以重构上述方法为
  @override  public boolean equals(Object o) {
return o instanceof CaseInsensitveString &&((CaseInsensitveString )o).s.equalsIgnoreCase(s);
}


传递性:如果一个对象等于第二个对象,第二个对象等于第三个对象,那么第一个对象一定等于第三个对象。
在父类和子类的情况下,子类将一个新的值组件添加到父类中,子类添加的信息就会影响到equals的比较结果。
    public  class Point() {
private final int x;
private final int y;
public Point(int x,int y) {
this.x=x;
this.y=y;
}
@override public boolean equals(Object o) {
if(!(o instanceof Point ))
return false ;
Point p =(Point)o;
retrun p.x==x&&p.y==y;
}

}
public class ColorPoint extends Point {
private final Color color ;
public ColorPonit(int x,int y,Color color) {
super(x,y);
this color =color;
}
….
}

在这段代码中equals比较的是Point而把点的颜色给忽略了。。。改为:
 @override public boolean equals(Object o) {
if(!(o instanceof ColorPoint ))
return false ;
retrun super.equals(o)&&((ColorPoint)o).color==color;
}

这种情况下在比较有色点和普通点,在相反的情况下则返回false如:
Point   p= new Point(1,2);
ColorPoint cp =new ColorPoint(1,2,Color.red);
p.equals(cp)
返回true cp.equals(p)返回false 违反了对称性

 @override public boolean equals(Object o) {
if(!(o instanceof Point ))
return false ;
if(!(o instanceof ColorPoint))
return o.equals(this);
retrun super.equals(o)&&((ColorPoint)o).color==color;
}

Point p1= new Point(1,2);
ColorPoint p2 =new ColorPoint(1,2,Color.red);
ColorPoint p3 =new ColorPoint(1,2,Color.blue);
P1.equals(p2); true
P1.equals(p3);true;
P2.equals(p3);false;

违反了传递性。
解决办法:在一个抽象的(abstract)类的子类中增加新的值组件
一个抽象的Shape类,他没有任何值组件,Circle子类增加了一个radius域,Rectangle子类增加了length和width域,只要不直接创建父类的实例,就可以使用equals进行子类中实例的比较。

一致性:如果两个对象相等,他们就必须始终保持相等,除非他们中有一个或者俩个都被修改了。当你在写一个类的时候考虑这个类是否是不可变的,如果他是不可变的,就必须保证equals方法满足相等的对象要永远相等,不相等的永远不相等。
非空性:所有的对象都必须不等于null,equals方法必须使用instanceof操作符,检查其参数是否为的正确的类型:
  @override public boolean equals (Object o) {
if(!(o instanceof MyType))
return false;
MyType mt =(MyType) o ;

}

总结实现equals方法:
1.使用“==”操作符检查“参数是否为这个对象的引用”。如果是,则返回true
2.使用instanceof操作符检查“参数是否为正确的类型”。如果不是则返回false
3.把参数转成正确的类型。
4.对于该类中的每个“关键域”,检查参数中是否与该对象中对应的域相匹配。
注意:不要将equals声明中的Object对象替换为其他的类型
Public boolean equals(MyClass o) {
...
} 这个方法并没有重写Object.equals.因为他的参数应该是Object类型的,相反他重载了Object.equals。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值