论坛首页 Java企业应用论坛

Effective Java 第8条的疑问

浏览 1520 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-03-06  

 

Symmetry—The second requirement says that any two objects must agree on

whether they are equal. Unlike the first requirement, it’s not hard to imagine vio-

lating this one unintentionally. For example, consider the following class, which

implements a case-insensitive string. The case of the string is preserved by

toString but ignored in comparisons:

// Broken - violates symmetry!

public final class CaseInsensitiveString {

private final String s;

public CaseInsensitiveString(String s) {

if (s == null)

throw new NullPointerException();

this.s = s;

}

// Broken - violates symmetry!

@Override public boolean equals(Object o) {

if (o instanceof CaseInsensitiveString)

return s.equalsIgnoreCase(

((CaseInsensitiveString) o).s);

if (o instanceof String)  // One-way interoperability!

return s.equalsIgnoreCase((String) o);

return false;

}

... // Remainder omitted

}

The well-intentioned equals method in this class naively attempts to interop-

erate with ordinary strings. Let’s suppose that we have one case-insensitive string

and one ordinary one:

CaseInsensitiveString cis = new CaseInsensitiveString("Polish");

String s = "polish";

As expected,  cis.equals(s) returns  true. The problem is that while the

equals method in  CaseInsensitiveString knows about ordinary strings, the

equals method in  String is oblivious to case-insensitive strings. Therefore

s.equals(cis) returns false, a clear violation of symmetry. Suppose you put a

case-insensitive string into a collection:

List<CaseInsensitiveString> list =

new ArrayList<CaseInsensitiveString>();

list.add(cis);

What does list.contains(s) return at this point? Who knows? In Sun’s cur-

rent implementation, it happens to return false, but that’s just an implementation

artifact. In another implementation, it could just as easily return true or throw a

runtime exception. Once you’ve violated the equals contract, you simply don’t

know how other objects will behave when confronted with your object.

To eliminate the problem, merely remove the ill-conceived attempt to interop-

erate with String from the equals method. Once you do this, you can refactor the

method to give it a single return:

@Override public boolean equals(Object o) {

return o instanceof CaseInsensitiveString &&

((CaseInsensitiveString) o).s.equalsIgnoreCase(s);

}

 

这段话最后说改成的代码是

public final class CaseInsenstiveString {
	private final String s;
	
	public CaseInsenstiveString(String s) {
		if(s == null) {
			throw new NullPointerException();
		} 
		this.s = s;
	}
	
	@Override
	public boolean equals(Object o) {
		return o instanceof CaseInsenstiveString &&
			((CaseInsenstiveString) o).s.equalsIgnoreCase(s);
	}
	
	public static void main(String[] args) {
		CaseInsenstiveString cis = new CaseInsenstiveString("test");
		String s = "test";
		System.out.println(cis.equals(s));
		System.out.println(s.equals(cis));
	}
}

 测试结果,cis为Test还是test都是false

疑问

那么他这里的说法的意思是 根本不让CaseInsentiveString和String进行比较(因为o instanceof CaseInsenstiveString就是false了),即类型不同怎么比都false

还是有其他意思?

 

从对称性来看,是成立了,但是这样的例子怎么感觉不是说的这个意思,请大家指点

论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics