effective java摘抄(一)
来源:互联网 发布:淘宝费列罗真假 编辑:程序博客网 时间:2024/06/05 08:20
一、覆盖equals请遵守通用约定
1、覆盖equals的约定
自反性:对于任何非null的引用值x,x.equals(x)必须返回true。
对称性:对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true。
传递性:对于任何非null的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)返回true,那么x.equals(z)也必须返回true。
一致性:对于任何非null的引用值x和y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)就会一致地返回true,或者一致的返回false。
对于任何非null的引用值x,x.equals(null)必须返回false。
2、违反对称性的案例:
public class CaseInsensitiveString {
private final String s;
public CaseInsensitiveString(String s){
if(s==null)
throw new NullPointerException();
this.s = s;
}
@Override
public boolean equals(Object o) {
if(o instanceof CaseInsensitiveString){
return s.equalsIgnoreCase(((CaseInsensitiveString) o).s);
}
if(o instanceof String)
return s.equalsIgnoreCase((String)o);
return false;
}
}
对于以上代码:如果假设现在有两个字符串,一个不区分大小写的,另一个是普通字符串
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";
cis.equals(s); //返回true
s.equals(cis); //返回false
虽然CaseInsensitiveString中的equals知道普通的字符串对象,但是String类中的equals方法并不知道不区分大小写的字符串,因此s.equals(cis)返回false。这就违反了对称性
3、违反对称性或传递性的案例:
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;
return p.x == x && p.y == y;
}
}
现在扩展当前类,为点增加颜色属性
public class ColorPoint extends Point{
private final Color color;
public ColorPoint(int x,int y,Color color){
super(x,y);
this.color = color;
}
@Override
public boolean equals(Object o) {
if(!(o instanceof ColorPoint)) return false;
return super.equals(o) && ((ColorPoint)o).color == color;
}
}
这个问题在于,比较普通点和有色点,以及有色点和普通点反过来对比时可能会得到不同的结果。普通点和有色点比较时忽略了颜色信息,但有色点和普通点比较时永远返回false因为参数的类型不正确。这违反了对称性,改进一下ColorPoint的equals方法让它符合对称性,但会牺牲传递性;
@Override
public boolean equals(Object o) {
if(!(o instanceof Point)) return false;
if(!(o instanceof ColorPoint)) return o.equals(this);
return super.equals(o) && ((ColorPoint)o).color == color;
}
这方法解决了对称性问题但牺牲了传递性
ColorPoint p1 = new ColorPoint(1, 2,Color.RED);
Point p2 = new Point(1,2);
ColorPoint p3 = new ColorPoint(1, 2,Color.BLUE);
System.out.println(p1.equals(p2)); //返回true
System.out.println(p2.equals(p3)); //返回true
System.out.println(p1.equals(p3)); //返回false
因为前两个比较中忽略了颜色信息,第三个比较中比较了颜色,并且颜色不同,所以返回false;
注意:我们无法在扩展可实例化的类的同事,既增加新的值组件,同时又保留equals约定,除非愿意放弃面向对象的抽象所带来的的优势。但是我们可以在一个抽象类的子类中增加新的值组件,而不会违反equals约定。
防止违反一致性,无论类是否可变,都不要使equals方法依赖于不可靠的资源。
4、实现高质量equals的方法的诀窍:
a、使用==操作符检查“参数是否为这个对象的引用”。
b、使用instanceof操作符检查“参数是否为正确的类型”。
c、把参数转换为正确的类型。
d、对于该类中的每个“关键(significant)”域,检查参数中的域是否与该对象中对应的域相匹配。如果这些测试全部返回成功,则返回true,否则返回false。
注意:1、覆盖equals方法时总要覆盖hashcode方法;2、不要企图让equals方法过于智能;3、不要将equals声明中的Object对象替换为其他的类型。
- effective java摘抄(一)
- effective java摘抄(二)
- Effective Java读书笔记一
- effective java读书笔记一
- 《Effective Java》读书笔记一
- Effective java 读书笔记(一)
- Effective Java读书笔记一
- Effective Java读书笔记一
- 《Effective Java》笔记(一)
- Effective Java(一)
- 【effective java】(一)
- 重读Effective Java(一)
- effective java 学习笔记(一)
- Effective Java 读书笔记(一)
- Effective Java 笔记(一)
- Effective Java 笔记(一)
- Effective Java读书笔记(一)
- 《Effective Java》 读后感(一)
- [置顶] 建造者模式——办理手机套餐
- mysql数据库常用操作命令集合
- Rikka with Tree HDU
- 0412
- 使用libcurl以Post方式向HTTP服务器提交数据
- effective java摘抄(一)
- “大数据可视化技术与应用”培训
- 557. Reverse Words in a String III
- 利用四元数,欧拉角进行空间向量旋转
- 友元函数
- Json转换利器Gson之实例三-Map处理(上)
- Android网络编程ConnectivityManager和NetworkInfo详解
- 正则
- JUST SO SO 之spring