java equals 原则与违反 - 点滴记忆*记忆点滴
收藏本站

java equals 原则与违反

Object 中equals的约定指出 equals 必须实现非空对象的等值关系:


◆自反性:对于如何非空值 x,表达式 x.equals(x) 应返回true。


◆对称性:对于任何非空值:x 和 y,x.equals(y) 应返回true,当且仅当 y.equals(x) 返回 true。


◆传递性:对于任何非空值 x、y、z,如果 x.equals(y)返回 true 并且 y.equals(z) 返回 true,那么x.equals(z) 应返回 true。


◆一致性:对于任何非空值:x 和 y,如果对象的equals比较中所用信息未被修改,多次调用 x.equals(y)应始终返回 true 或始终返回 false。


◆对于任何非空值 x,x.equals(null) 应返回 false。


违反示例:

 自反性,较容易避免,一般是equals 方法逻辑有明显问题:


public class Bo {

	private String id;
	
	public Bo(){
		
	}
	
	public Bo(String id){
		this.id = id;
	}
	
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	@Override
	public boolean equals(final Object other) {
		return false;
	}

	@Override
	public int hashCode() {
			return new HashCodeBuilder().append(id).toHashCode();
	}
	public static void main(String[] args) {
		Bo b = new Bo();
		System.out.println(b.equals(b));// return false
	}
}
对称性,这是人们常会换的错误:



//重写上例Bo equals 方法
	@Override
	public boolean equals(final Object other) {
			if (!(other instanceof Bo))
				return false;
			Bo castOther = (Bo) other;
			return new EqualsBuilder().append(id, castOther.id).isEquals();
	}

//增加子类C
public class Co extends Bo {
	
	public Co(){
		
	}
	
	public Co(String id,String name){
		super(id);
		this.name = name;
	}

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public boolean equals(final Object other) {
			if (!(other instanceof Co))
				return false;
			Co castOther = (Co) other;
			return new EqualsBuilder().append(name, castOther.name).isEquals() &&
					super.equals(other);
	}
	
	public static void main(String[] args) {
		Bo b = new Bo("1");
		Co c1 = new Co("1","center");
		System.out.println(b.equals(c1)); // true
		System.out.println(c1.equals(b));// false
                
	}
}




传递性,这也是常遇到的:

public class Co extends Bo {
	
	public Co(){
		
	}
	
	public Co(String id,String name){
		super(id);
		this.name = name;
	}

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public boolean equals(final Object other) {
		boolean result = false;  
		 if (other instanceof Co) {  
			 Co that = (Co) other;  
			 result = (this.name.equals(that.name) && super.equals(that));  
		 }else if (other instanceof Bo) {  
			 Bo that = (Bo) other;  
			 result = that.equals(this);  
		 }  
		 return result;
	}
	
	public static void main(String[] args) {
		Bo b = new Bo("1");
		Co c1 = new Co("1","au");
		Co c2 = new Co("1","bu");
		System.out.println(b.equals(c1));
		System.out.println(c1.equals(b));
		
		System.out.println(c2.equals(b));
		
		System.out.println(c1.equals(c2)); //违反传递性
	}
}
后两种特性违反情况较少,可自举例。

另外还需要注意的:

1. equals 方法是 Override ,而不能重载

2. 对象域是非final 时,注意存储在set 中后更改域值后 调用contains 返回错误。

    留下足迹