分享

java equals使用instanceof还是getClass?

 hh3755 2014-08-07

'm using Eclipse to generate .equals() and .hashCode(), and there is an option labeled "Use 'instanceof' to compare types". The default is for this option to be unchecked and use .getClass() to compare types. Is there any reason I should prefer .getClass() over instanceof?

Without using instanceof:

if (obj == null)
  return false;
if (getClass() != obj.getClass())
  return false;

Using instanceof:

if (obj == null)
  return false;
if (!(obj instanceof MyClass))
  return false;

I usually check the instanceof option, and then go in and remove the "if (obj == null)" check. (It is redundant since null objects will always fail instanceof.) Is there any reason that's a bad idea?

share|improve this question

10 Answers

up vote 44 down vote accepted

If you use instanceof, making your equals implementation final will preserve the symmetry contract of the method: x.equals(y) == y.equals(x). If final seems restrictive, carefully examine your notion of object equivalence to make sure that your overriding implementations fully maintain the contract established by the Object class.

share|improve this answer
    
exactly that came to my mind when i read the josh bloch quote above. +1 :) –  Johannes Schaub - litb Feb 27 '09 at 21:43
3  
definitely the key decision. symmetry must apply, and instanceof makes it very easy to be asymmetric accidentally –  Scott Stanchfield Mar 3 '09 at 20:15

Josh Bloch favors your approach:

The reason that I favor the instanceof approach is that when you use the getClass approach, you have the restriction that objects are only equal to other objects of the same class, the same run time type. If you extend a class and add a couple of innocuous methods to it, then check to see whether some object of the subclass is equal to an object of the super class, even if the objects are equal in all important aspects, you will get the surprising answer that they aren't equal. In fact, this violates a strict interpretation of the Liskov substitution principle, and can lead to very surprising behavior. In Java, it's particularly important because most of the collections (HashTable, etc.) are based on the equals method. If you put a member of the super class in a hash table as the key and then look it up using a subclass instance, you won't find it, because they are not equal.

See also this SO answer.

Effective Java chapter 3 also covers this.

share|improve this answer
2  
+1 Heh as soon as I saw this question I thought of the Josh Bloch quote. –  cletus Feb 27 '09 at 22:11
    
@cletus: I couldn't believe that no one had posted it before I did. –  Michael Myers? Feb 27 '09 at 22:12
3  
+1 Everyone doing java should read that book at least 10 times! –  André Feb 27 '09 at 23:32
1  
The problem with the instanceof approach is that it breaks the "symmetric" property of Object.equals() in that it becomes possible that x.equals(y) == true but y.equals(x) == false if x.getClass() != y.getClass(). I prefer not to break this property unless absolutely necessary (i.e., overriding equals() for managed or proxy objects). –  Kevin Sitze Jun 25 '13 at 23:13
1  
The instanceof approach is proper when, and only when, the base class defines what equality among subclass objects should mean. Using getClass does not violate the LSP, since the LSP merely relates to what can be done with existing instances--not what kinds of instances can be constructed. The class returned by getClass is an immutable property of an object instance. The LSP does not imply that it should be possible to create a subclass where that property indicates any class other than the one which created it. –  supercat Jan 30 at 0:14

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多