Thursday, August 19, 2021

How to use instanceof operator in Java with example

The instanceof operator in Java is used to check if an object belongs to a particular type or not at runtime. It's also a built-in keyword in Java programming language and is mostly used to avoid ClassCastException in Java. It is used as a safety check before casting any object into a certain type. This operator has a form of object instanceof Type and returns true if the object satisfies IS-A relationship with the Type i.e. object is an instance of class Type or object is the instance of a class which extends Type or object is an instance of a class which implements interface Type.

Once an object passed the instanceof check, it's safe to type-cast into that type, without worrying of java.lang.ClassCastException.

By the way, instanceof operator is also a rather lesser-used operator in Java, similar to transient and volatile, and many programmers don't even know the basics of this operator. If you are one of those then you must read this article and bookmark it for future reference.

And, if you are serious about improving your Hibernate and JPA skills then I also recommend you check out Master Hibernate and JPA with Spring Boot in 100 Steps course by Ranga Rao Karnam on Udemy. It's a great course to learn Hibernate and JPA with Spring Boot in a hands-on and practical manner. 

10 things about instanceof operators in Java

Good knowledge of instanceof operator is essential for Java developers, but It's, even more, important for those JEE developers, who are working in Hibernate, as instanceof has a big role to play in overriding equals() and hashCode() of Hibernate persistent class.




Since Hibernate proxies everything, it's not possible to use the getClass() method for type checking, you need to rely on the instanceof operator for that. You can also expect a few questions from the instanceof operator in the OCPJP exam or any core Java interview.

1) instanceof operator will return false if the object is null. For example in the following code, control will not go inside if() block if the object's value is null.

if(object instanceof Order){
    Order ord = (Order) object;
}

You can use this property of the instanceof operator while overriding the equals() method in Java.


2) The instanceof operator is primarily used to check whether an object is of a certain type or not. In fact, the instanceof operator provides a way to perform runtime type identification in Java, which is unlike C++, not supported by Java. Alternatively, you can also use the getClass() method from java.lang.Class for the same purpose. See the article 2 ways of runtime type identification in Java for more details.


3) One of the most prominent uses of the instanceof operator is to implement the equals() method for Hibernate persistent class. Since Hibernate uses a proxy object, it's not safe to do a type check in equals() method using the getClass() method, as it will never succeed. 

Other ways to doing type check e.g. Hibernate.getClass() method will make your entity class dependent on a third-party library and if you want to share your persistent class then you also need to include Hibernate, which is not good at all. That's the reason, I prefer the instanceof operator for doing type checking in the equals() method of Entity class, as shown below:

@Override
public boolean equals(Object object) {
   // instanceof also takes care of null check
   if (!(object instanceof Customer)) {
      return false;
   }
   Customer other = (Customer) object;
     
   // rest of code omitted for brevity
}

Since the instanceof operator in Java returns true for the instance of a subclass, this code will work fine with Hibernate proxy classes, which inherit from the persistent class. By the way, instanceof check also breaks equals() method's symmetrical contract, according to that if a.equals(b) is true then b.equals(a) should also be true, but with the instanceof operator in use, if a representative instance of the parent class and b being an instance of the child class, a.equals(b) will return true but b.equals(a) will return false, thus breaking equals() contract of symmetry. Though it's not a real issue until you are doing such comparison e.g. in the Hibernate persistent class.

What is instanceof operator in Java with example



Java instanceof Example

Here is a sample Java Program to demonstrate the capability of instanceof operators in Java. First, we have created a couple of classes and interfaces to define type hierarchy. We have a class called ObjectOriented and an interface JVMLanguage

Then we have another class called Java which extends ObjectOriented and implements JVMLanguage and another class called CPlusPlus which only extends the ObjectOriented class. 

Now with this setup, we will test the instanceof operator to determine whether an object is an instance of any of these classes or not.

class ObjectOriented {
}

class Java extends ObjectOriented implements JVMLanguage {
}

class CPlusPlus extends ObjectOriented {
}

interface JVMLanguage {
}

import java.io.File;
import java.io.IOException;
import java.util.Scanner;
/**
 *
 * @author Javin Paul
 *
 */
public class InstanceOfDemo {

    public static void main(String[] args) {

        ObjectOriented oops = new ObjectOriented();
        Java java = new Java();
        CPlusPlus cpp = new CPlusPlus();

        // true - because oops is direct instance of ObjectOriented class
        System.out.println("oops instanceof ObjectOriented : " 
                 + (oops instanceof ObjectOriented));

        // true - because java is instance of Java class,
                  which is sub-class or ObjectOriented
        System.out.println("java instanceof ObjectOriented : "
                       + (java instanceof ObjectOriented));

        // true - because java is object of Java class, 
                  which implements JVMLanguage interface
        System.out.println("java instanceof JVMLanguage : " 
                              + (java instanceof JVMLanguage));

        // true - because cpp is object of CPlusPlus,
                  which extends ObjectOriented
        System.out.println("cpp instanceof ObjectOriented : "
                             + (cpp instanceof ObjectOriented));

        // true - because cpp is object of type CPlusPlus
        System.out.println("cpp instanceof CPlusPlus: " 
                           + (cpp instanceof CPlusPlus));

        // false - because oops is instance of ObjectOriented,
                neither extends Java class, nor implement Java interface
        System.out.println("oops  instanceof Java : " 
                       + (oops instanceof Java));

        //Java fromOops = (Java) oops; // compile ok 
                                       //- classCastException at runtime
     
        // false - because ObjectOriented class does not implement
                   JVMLanguage interface
        System.out.println("oops  instanceof JVMLanguage : "
                          + (oops instanceof JVMLanguage));

        //JVMLanguage jvm = (JVMLanguage) oops; // compile fine
                                  // - java.lang.ClassCastException at runtime
     
     
        // false - because CPlusPlus class does not implement
                     JVMLanguage interface
        System.out.println("cpp instanceof JVMLanguage : "
                        + (cpp instanceof JVMLanguage));

        // instanceof operator returns false if compared to null
        java = null;
        System.out.println("(java =null) instanceof ObjectOriented : "
                               + (java instanceof ObjectOriented));
        System.out.println("(java =null) instanceof Java : " 
                        + (java instanceof Java));
    }
}


Output:
oops instanceof ObjectOriented : true
java instanceof ObjectOriented : true
java instanceof JVMLanguage : true
cpp instanceof ObjectOriented : true
cpp instanceof CPlusPlus: true
oops  instanceof Java : false
oops  instanceof JVMLanguage : false
cpp instanceof JVMLanguage : false
(java =null) instanceof ObjectOriented : false
(java =null) instanceof Java : false

You can also run this program by uncommenting certain code which fails instanceof check and subsequent cast will throw java.lang.ClassCastException. This program is self-explanatory, but you should pay attention when instanceof returns false, you can clearly see that it returns true only when we have an IS-A relationship satisfied between A and B in check of A instanceof B. If A is null or there is no IS-A relationship, it will return false and any attempt to cast B into A will throw ClassCastException.

That’s all about what is the instanceof operator in Java and how to use the instanceof operator. In defensive programming, an instanceof check is a must before casting any unknown object. By default don't use the instanceof operator for type checking in equals(), as it breaks the symmetry contract, but remember to use it while overriding equals() for Hibernate persistent class.


Other Hibernate Articles and Interview Questions you may like
  • Difference between First and Second level cache in Hibernate? (answer)
  • Difference between get() and load() method in Hibernate? (answer)
  • 5 Spring and Hibernate Training Courses for Java developers (list)
  • 2 Books to Learn Hibernate for Beginners (books)
  • 5 Books to Learn Spring Framework for Beginners (books)
  • Why Hibernate Entity class should not be final in Java? (answer)
  • 10 Hibernate Questions from Java Interviews (list)
Thanks for reading this article, if you like this article and the interview question then please share it with your friends and colleagues. If you have any questions or feedback then please drop a comment.

2 comments:

  1. Nice post but I think the first code has a little error

    where is read
    if(object instanceof Order){ Order ord = (Order) order; }

    should be
    if(object instanceof Order){ Order ord = (Order) object; }

    ReplyDelete
  2. @Walter, that's right, thanks for pointing it out. I have corrected it now.

    ReplyDelete