Search code examples
javainstanceof

How to assign instanceof type to a variable?


I am wondering if it is possible and how to store a type reference into a variable so that it can be later used with the instanceof operator.

For example

Book book = new Book("My Favourite Book", "Some Author");

BookType bookType = Book;

if(book instanceof bookType){
    // Do something
}

Instead of having to hard code it:

Book book = new Book("My Favourite Book", "Some Author");

if(book instanceof Book){
    // Do something
}

Is it possible to get the Book type from Book.class maybe using reflection?

I did not found much about this topic.

Note that this is not the same as using

Book.class.isInstance(book);
Object value = Book.class.cast(book);

because I would lose all the methods of the Book class.


Solution

  • The closest to what you originally asked1 for is something like this:

       Class<?> clazz = Book.class;
    
       Object someObject = new Book(...);
       
       if (clazz.isInstance(someObject)) {
          Object instanceOfClazz = clazz.cast(someObject);
          // ...
       }
    

    (Note that this Q&A - Is there something like instanceOf(Class<?> c) in Java? - directly answers the question in the your question title.)

    But you objected that the result of the cast call:

    "would lose all the methods of the Book class".

    First of all that is not technically correct. The object that instanceOfClazz refers to is still and will always remain a Book. It still has and will always have all of the methods of a Book.

    But you do have a point (I think). You cannot use the cast call's result effectively in the above code because you assigned it to a variable whose type is Object. And you cannot call Book methods via a variable / value whose static type is Object.

    If instead we had written this:

       Class<Book> clazz = Book.class;
    
       Object someObject = new Book(...);
       
       if (clazz.isInstance(someObject)) {
          Book book = clazz.cast(someObject);
          // call some `Book` methods.
       }
    

    Now you can call Book methods on book. But the gotcha is that we had to write Class<Book> instead of Class<?> (or Class) to make that work. So we have ended up wiring the class name Book into the code anyway. Ooops!

    The fundamental problem is that Java code cannot make regular method calls on an object unless the compiler knows what its type is ... and that it has those methods. If you want to invoke Book methods in cases where the static type of the variable is (say) Object, then you have to use reflection to do it. Something like this:

      if (clazz.isInstance(someObject)) {
          Method method = clazz.getMethod("setNosPages", int.class);
          method.invoke(someObject, 99);
      }
    

    and deal with the various exceptions that that might throw.

    Basically, you refer to the class and methods by name in the code, or you use reflection.


    "I need to assign the object/value parsed from a json to a field of type Book (or other types accordingly) of another class."

    It won't work. Java is a statically typed language2. Think of another way to solve the problem. For example, use reflection to assign to the field.


    1 - That is ... what the words of your question originally asked!
    2 - OK ... that is over-simplifying.