В чем разница между instanceof и getclass в java
Перейти к содержимому

В чем разница между instanceof и getclass в java

  • автор:

Type matching in Java equals — getClass() vs. instanceof

There is an ongoing dispute on how type matching in the equals method should be implemented. A nice overview article can be found in Angelika Langers Secrets of equals() — Part 1 where you can find additional useful references. In short there are two possible ways to test the object’s type in the equals method:

The properties of the getClass() approach can be summarized as:

  • you can add fields into the subtypes and use them in subtype’s equals method. The notoriously popular example is that of subclassing the Point class to a ColorPoint class by adding an extra color field to it. The overridden equals in ColorPoint can match the point’s coordinates and also it’s color.
  • The drawback of this approach is that the supertype Point can never be equal to its subtype ColorPoint (a good example is in Josh Bloch’s book Effective java, chapter 3)

Simply put in the instanceof approach:

the subtype and supertype can be equal,

but equals is constrained to matching supertype fields only. The instanceof in supertype’s equals method does not reveal which type of the class hierarchy you are currently examining. As a result you only use supertype’s equals method and therefore you check only fields common to all types in the hierarchy. There is no way to add a field in a subtype that will be checked in the subtype’s overridden equals method without breaking the properties of equivalence relation.

At this point we see that one can argue for both approaches, but there is another aspect that makes a big difference. The former approach does not conform to the Liskov Substitution Principle — LSP while the latter does. For starters a good description of LSP is in the article from Robert C. Martin, the original Liskov paper is a bit tough to read. There are several formulations of LSP, I think about LSP as:

The subtype can’t break the contract between the supertype and method (function) where it is used.

Although the getClass() approach breaks LSP the debate around getClass() vs. instanceof still goes on.

On both projects I’ve worked so far (I am a junior dev) the getClass() approach was used for “better flexibility”. Although the LSP is a design guideline not a rigid OO theorem there are numerous simple examples where not following the LSP might cause problems. Consider a Shape class that checks whether a Point is the Shape s center:

If this method is called with a ColorPoint the result is false although the ColorPoint might have the shapes center coordinates. The ColorPoint violates the conditions of the isCentre method which was imposed by the isCentre ⇿ Point contract and thus breaks the LSP. This behaviour is a trap for a developers.

A safe way to do type matching that conforms to OO principles is by using the instanceof operator. It is of course true that systems can be also implemented with the getClass() approach, you just won’t be able to rely on the logical equivalence in the system.

instanceof vs getClass in equals method in Java

Akash Deep

As we use equals() and HashCode() methods while creating objects in Java, but most of us don’t know how to use them properly. In this post i’ll explain which to use and when.

Object.equals() provides a default implementation of equality-comparison and at times the default implementation is just fine and semantically correct for a newly defined class. In other situations the new class must override equals() to provide meaningful and semantically correct equality-comparison. instanceof approach is favoured when we use 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 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 in below example:

class B extends A

Object oA = new A(); Object oB = new B();

oA instanceof A => true oA instanceof B => false oB instanceof A => true // <================ HERE oB instanceof B => true

instanceof Vs getClass( )

I see gain in performance when using getClass() and == operator over instanceOf operator.

Is there any guideline, which one to use getClass() or instanceOf ?

Given a scenario: I know exact classes to be matched, that is String , Integer (these are final classes), etc.

Is using instanceOf operator bad practise ?

Dhananjay's user avatar

4 Answers 4

The reason that the performance of instanceof and getClass() == . is different is that they are doing different things.

instanceof tests whether the object reference on the left-hand side (LHS) is an instance of the type on the right-hand side (RHS) or some subtype.

getClass() == . tests whether the types are identical.

So the recommendation is to ignore the performance issue and use the alternative that gives you the answer that you need.

Is using the instanceOf operator bad practice ?

Not necessarily. Overuse of either instanceOf or getClass() may be "design smell". If you are not careful, you end up with a design where the addition of new subclasses results in a significant amount of code reworking. In most situations, the preferred approach is to use polymorphism.

However, there are cases where these are NOT "design smell". For example, in equals(Object) you need to test the actual type of the argument, and return false if it doesn’t match. This is best done using getClass() .

Java — Difference between getClass() and instanceof in equals() method?

This can break the symmetry clause of the equals() method but can also be leveraged for flexibility and performance as Hibernate does by using proxies in place of actual classes. Let’s see some code examples to understand this difference better.

Difference between instanceof vs getClass() in Java

So, you can see that getClass() put a restriction that objects are only equal to other objects of the same class, the same runtime type, but instanceof operator returns true for subclass as well.

If you use the getClass() in the equals() method then it will only return true if the other object is also of the same class or same runtime type, it will return false even if its object of subclass and follow the Liskov substitution principle.

Java - Difference between getClass() and instanceof in equals() method?

The instanceof operator lets you implement equality between super class and sub class. This is very important from the Collections framework perspective which uses the equals() method to find values. If you use the instanceof operator in equals() method then you can retrieve values even with the object of the subclass as a key provided they have the same content, but this is not possible when you use the getClass() method.

Hibernate relies for its performance gain on this behavior of instanceof operator. If you remember, there is a restriction in place for any Entity or Persistence class in Hibernate that it cannot be final.

This is because hibernate internally creates Proxy classes by extending your Entity class and use it until you really need an attribute from the database. Since instanceof is used to verify the type of object, a Proxy can be equal to the original object.

On the other hand, using instanceof operator has one disadvantage as well. It doesn’t respect the symmetry contract of equals() method. The symmetry property says that if x.equals(y) is true then y.equals(x) should also be true, but if you swap x with subclass then x instanceof y would be true but y instanceof x will be false, hence equals() method will return false.

This is the fact you should consider when deciding whether to use getClass() or instanceof operator for overriding equals() in Java.

That’s all on the difference between getClass() and instanceof in Java. Just remember that getClass() return false if you compare it with the instanceof the subclass but the instance of operator trues if the object is a subclass of the class on the right-hand side of the operator.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *