`
xusulong
  • 浏览: 79893 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Effective Java 第8条的疑问

阅读更多

 

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

还是有其他意思?

 

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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics