Jesse Haniel
Lead Software Architect at Tribunal de Justiça da Paraíba

Java instanceof Operator

Published in the Java Developer group
members
Hi! Today we'll talk about the instanceof operator, consider examples of how it is used, and touch on some aspects of how it works:) You've already encountered this operator on early levels of CodeGym. Do you remember why we need it? If not, no worries. Let's remember together. The instanceof operator is needed to check whether an object referenced by an X variable was created based on some Y class. That sounds simple. Why have we returned to this topic?How the instanceof operator works - 1First of all, because now you're well acquainted with Java's inheritance mechanism and the other principles of OOP. The instanceof operator will now be much clearer and we'll look at more advanced examples of how it is used. Let's go! You probably remember that the instanceof operator returns true if the check evaluates to true, or false if the expression is false. Accordingly, it usually occurs in all sorts of conditional expressions (if…else). Let's start with some simpler examples:
public class Main {

   public static void main(String[] args) {

       Integer x = new Integer(22);

       System.out.println(x instanceof Integer);
   }
}
What do you think will be displayed on the console? Well, it's obvious here.:) The x object is an Integer, so the result will be true. Console output: True Let's try checking whether it's a String:
public class Main {

   public static void main(String[] args) {

       Integer x = new Integer(22);

       System.out.println(x instanceof String); // Error!
   }
}
We got an error. And pay attention: the compiler generated the error before running the code! It immediately saw that Integer and String cannot be automatically converted to each other and are not related through inheritance. Consequently, an Integer object is not created based on String. This is convenient and helps avoid strange runtime errors, so the compiler helped us out here :) Now let's try to consider examples that are more difficult. Since we mentioned inheritance, let's work with the following small system of classes:
public class Animal {

}

public class Cat extends Animal {

}

public class MaineCoon extends Cat {

}
We already know how instanceof behaves when we check whether an object is an instances of a class, but what happens if we consider the parent-child relationship? For example, what do you think these expressions will yield:
public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();

       System.out.println(cat instanceof Animal);

       System.out.println(cat instanceof MaineCoon);

   }
}
Output: True False The main question that needs to be answered is exactly how instanceof interprets 'object created based on a class'? 'cat instanceof Animal' evaluates to true, but surely we can find fault with that wording. Why is a Cat object created based on the Animal class? Isn't it created based on its own class alone? The answer is simple enough, and you may have already thought of it. Remember the order in which constructors are called and variables are initialized when creating an object. We already covered this topic in the article about class constructors. Here's an example from that lesson:
public class Animal {

   String brain = "Initial value of brain in the Animal class";
   String heart = "Initial value of heart in the Animal class";

   public static int animalCount = 7700000;

   public Animal(String brain, String heart) {
       System.out.println("Animal base class constructor is running");
       System.out.println("Have the variables of the Animal class already been initialized?");
       System.out.println("Current value of static variable animalCount = " + animalCount);
       System.out.println("Current value of brain in the Animal class = " + this.brain);
       System.out.println("Current value of heart in the Animal class = " + this.heart);
       System.out.println("Have the variables of the Cat class already been initialized?");
       System.out.println("Current value of static variable catCount = " + Cat.catCount);

       this.brain = brain;
       this.heart = heart;
       System.out.println("Animal base class constructor is done!");
       System.out.println("Current value of brain = " + this.brain);
       System.out.println("Current value of heart = " + this.heart);
   }
}

public class Cat extends Animal {

   String tail = "Initial value of tail in the Cat class";

   static int catCount = 37;

   public Cat(String brain, String heart, String tail) {
       super(brain, heart);
       System.out.println("The Cat class constructor has started (The Animal constructor already finished)");
       System.out.println("Current value of static variable catCount = " + catCount);
       System.out.println("Current value of tail = " + this.tail);
       this.tail = tail;
       System.out.println("Current value of tail = " + this.tail);
   }

   public static void main(String[] args) {
       Cat cat = new Cat("Brain", "Heart", "Tail");
   }
}
And if you run it in the IDE, the console output will look like this: Animal base class constructor is running Have the variables of the Animal class already been initialized? Current value of static variable animalCount = 7700000 Current value of brain in the Animal class = Initial value of brain in the Animal class Current value of heart in the Animal class = Initial value of heart in the Animal class Have the variables of the Cat class already been initialized? Current value of static variable catCount = 37 Animal base class constructor is done! Current value of brain = Brain Current value heart = Heart The cat class constructor has started (The Animal constructor already finished) Current value of static variable catCount = 37 Current value of tail = Initial value of tail in the Cat class Current value of tail = Tail Now do you remember?:) The constructor of the base class, if there is a base class, is always called first when creating an object. The instanceof operator is guided by this principle when trying to determine whether an A object was created based on a B class. If the base class constructor is called, then there can be no doubt. With the second check, everything is simpler:
System.out.println(cat instanceof MaineCoon);
The MaineCoon constructor was not called when the Cat object was created, which makes sense. After all, MaineCoon is a descendant of Cat, not an ancestor. And it is not a template for Cat. Okay, I think we're clear on that. But what happens if we do this?:
public class Main {

   public static void main(String[] args) {

       Cat cat = new MaineCoon();

       System.out.println(cat instanceof Cat);
       System.out.println(cat instanceof MaineCoon);


   }
}
Hmm... now that's harder. Let's talk it over. We have a Cat variable to which we assigned a MaineCoon object. By the way, why does that even work? We can do that, right? Yes, we can. After all, every MaineCoon is a cat. If that's not entirely clear, remember the example of widening primitive types:
public class Main {

   public static void main(String[] args) {

       long x = 1024;

   }
}
The number 1024 is a short: it easily fits into a long variable, since there are enough bytes to accommodate it (remember the example with the dolls?). A descendant object can always be assigned to an ancestor variable. For now, just remember this, and in subsequent lessons we'll analyze how it works. So what does our example output?
Cat cat = new MaineCoon();
System.out.println(cat instanceof Cat);
System.out.println(cat instanceof MaineCoon);
What will instanceof check? our Cat variable or our MaineCoon object? The answer is this question is actually simple. You just need to read the definition of the operator again: The instanceof operator is needed to check whether an object referenced by an X variable was created based on some Y class. The instanceof operator tests the origin of an object, not the variable type. Thus, in this example, our program will display true in both cases: we have a MaineCoon object. Obviously, it was created based on the MaineCoon class, but it was created based on the Cat parent class as well!
Comments (18)
  • Popular
  • New
  • Old
You must be signed in to leave a comment
蓝色幽灵
Level 22 , Nanning, China
24 April, 01:27
Main.java:9: error: invalid method declaration; return type required public Animal(String brain, String heart) { ^ 1 error why?
Kent Hervey Software Engineer/Consult at Zeal IT Consultants
1 February 2021, 20:18
Output did not seem to be right, so I pasted into IDE and ran...sure enough...it needs some fixing
Gellert Varga
Level 23 , Szekesfehervar, Hungary
26 February 2021, 09:24
The mistake has already been fixed. See lines 14 and 15.
Chang You
Level 47 , Santa Rosa, United States
25 December 2020, 06:24
Doubts cleared
Chandan Thapa
Level 22 , Dubai, United Arab Emirates
25 November 2020, 15:48
Clear clear crystal clear!
HaeWon Chung
Level 17 , Boston, United States
17 May 2020, 19:43
Below code is missing some statements compare to the link and thus the expected results of the code is different from what is shown here.
public Animal(String brain, String heart) {
    System.out.println("Animal base class constructor is running");
    System.out.println("Have the variables of the Animal class already been initialized?");
    System.out.println("Current value of static variable animalCount = " + animalCount);
    System.out.println("Current value of brain in the Animal class = " + this.brain);
    System.out.println("Current value of heart in the Animal class = " + this.heart);
Adrian
Level 27 , Spanish Town, Jamaica
11 June 2020, 20:03
yup. i spent a while going over it, trying to understand why the output had text that was not in the code itself. they should correct that.
Gellert Varga
Level 23 , Szekesfehervar, Hungary
26 February 2021, 09:23
I told CodeGym this. It was fixed right away. So, this mistake is no longer exist in the lesson. See line 14-15.
HaeWon Chung
Level 17 , Boston, United States
17 May 2020, 19:27
I don't understand why below code doesn't compile
public class Main {

   public static void main(String[] args) {

       Integer x = new Integer(22);

       System.out.println(x instanceof String); // Error!
   }
}
I thought it should display False instead of compiling error. Can anyone give me an example where X instance of Y gives False, and what's the difference between that and the above code?
Zourkas
Level 16 , Frankfurt, Germany
16 March 2021, 13:57
From what I understood when we use "instanceof" operator for objects that have no parent-child relationship with each other, we get an Error. On the other hand when parent-child relationship is involved then a false evaluation, with some modifications in code, can become true whereas in Integer-String example true is never a case. You can never create an object of Integer based on String class. Check this out: public class Solution { public static void main(String[] args) { Cat cat = new Cat(); System.out.println(cat instanceof Animal); System.out.println(cat instanceof MaineCoon); } public static class Animal {} public static class Cat extends Animal {} public static class MaineCoon extends Cat {} } Output: true false Now in the above code if you replace Cat cat = new Cat(); with Cat cat = new MaineCoon(); your false becomes true. Output: true true
Khongpak Phupkdee
Level 15 , Chiangrai, Thailand
22 August 2021, 14:51
the compiler generated the error before running the code! It immediately saw that Integer and String cannot be automatically converted to each other and are not related through inheritance. Consequently, an Integer object is not created based on String.
Jakub Góźdź
Level 31 , Katowice, Poland
19 February 2020, 10:28
Easy to understand when explained in such a wonderful way :)
Nyerges Ferenc
Level 23 , Bükkábrány, Hungary
20 January 2020, 16:03
That's an eye-opening lesson indeed
Fadi Alsaidi
Level 32 , Carrollton, TX, USA
5 January 2020, 17:36
So basically, X instance of Y is true if: 1-Y is a parent class of X 2-Y is referenced in X class got it. I am starting to wonder if I should always reference/initialize an object by it's parent class..hmmmm
Seb
Level 41 , Crefeld, Germany
11 January 2020, 20:40
No, you should not always reference/initialize an object by its parent class. If you did, you might not be able to access all the features of your actual class. Let's consider the example that you have created a Car class and that you also created a Formula1Car class, which inherits from Car. If you now add a pitStop() method to the Formula1Car class, you wouldn't be able to call this method on an object referenced by the Car class. Code Example: Car car = new Formula1Car(); car.pitStop(); // -> that doesn't work - because the Car class doesn't know this method Formula1Car f1car = new Formula1Car(); f1car.pitStop(); // -> that works - because the Formula1Car class knows this method
Fadi Alsaidi
Level 32 , Carrollton, TX, USA
11 January 2020, 21:27
Thanks. that makes sense. Any insight/rule when should we reference the parent or inherited class? it is very cumbersome to cast the object variable to access it's methods. to me this looks very messy ((Formula1Car)car).pitStop();
Seb
Level 41 , Crefeld, Germany
11 January 2020, 22:44
I don't know of any particular rule when to use what, but I think it's fair to say that one usually recognises what to use out of the specific context. So, basically the fact that you're aware of these different options is all you need for now. Cheers. :-)
6 August 2019, 21:51
instanceof understood!