Java instanceof operator
Jakob Jenkov |
The Java instanceof operator can determine if a given Java object is an instance of a given class, superclass or interface. This is useful if you have an object of an unknown type and you need to cast it to a known type to use it as intended.
The Java instanceof operator is also referred to as a type comparison operator because it compares the type of a given instance (object) with a specific type (class or interface).
Java instanceof Example
To understand how the Java instanceof operator works, let us look at a simple Java instanceof example:
import java.util.HashMap; import java.util.Map; public class InstanceofExample { public static void main(String[] args) { Map<Object, Object> map = new HashMap(); boolean mapIsObject = map instanceof Object; System.out.println(mapIsObject); } }
Notice the statement:
boolean mapIsObject = map instanceof Object;
The expression map instanceof Object
will evaluate to true
if the map
variable references an object that is an instance of class Object
, or any subclass of class Object
. Since all
classes in Java inherit from Object, this expression will evaluate to true
.
Instanceof With Same Class
As mentioned earlier, the Java instanceof operator will evaluate to true if you compare an object to the exact class of that object. Here is a Java instanceof example showing a comparison of an object to its exact class:
HashMap<Object, Object> map = new HashMap(); boolean mapIsObject = map instanceof HashMap;
The last line of this example will set mapIsObject
to true
because the
map
variable references an object of type HashMap.
Note that it is the actual type of the referenced object that is compared against - not the type of the variable referencing the object. Here is another Java instanceof example illustrating that:
Map<Object, Object> map = new HashMap(); boolean mapIsObject = map instanceof HashMap;
Notice that the type of the variable is now Map
and not HashMap
. Map is not a subclass
of HashMap. Thus, a Map is not guaranteed to be an instance of a HashMap. However, since the actual object
assigned to the map
variable is a HashMap object, the second line of the example will still
evaluate to true
.
Instanceof With Superclass
As also mentioned earlier, the Java instanceof operator also evaluates to true
when comparing
an object against a superclass of the type of that object. Here is a Java instanceof example illustrating that:
Map<Object, Object> map = new HashMap(); boolean mapIsObject = map instanceof Object;
Since HashMap is a subclass of Object - even if not a direct subclass, the expression
map instanceof Object
evaluates to true.
Note, that it does not matter how high up in the inheritance hierarchy the compared type is superclass of
the type of the object. As long as the type compared to is a superclass somewhere up the inheritance hierarchy,
instanceof will evaluate to true
.
Instanceof With Interface
The Java instanceof operator also works when comparing an object against an interface instead of a class. Here is a Java instanceof example showing that:
HashMap<Object, Object> map = new HashMap(); boolean mapIsObject = map instanceof Map;
Notice, that even if the map
variable is of type HashMap, the instanceof operator returns
true
for the expression map instanceof Map
because the HashMap class implements
the Map interface. This would also be true if the variable was of type Map, as in this example:
Map<Object, Object> map = new HashMap(); boolean mapIsObject = map instanceof Map;
Instanceof With Superinterface
The Java instanceof operator also evaluates to true when comparing an object against a superinterface which the class of the object, or a superclass of the object implements. Here is a Java instanceof example illustrating that:
SortedMap<Object, Object> map = new TreeMap(); boolean mapIsObject = map instanceof Map;
The SortedMap interface extends the Map interface. Map is thus a superinterface of SortedMap. The TreeMap class implements
SortedMap, and thus also indirectly the Map interface. Thus, the last line of the example evaluates to
true
Instanceof With null
The Java instanceof operator always evaluates to false
when a null
variable is
compared against any class or interface. Here is a Java instanceof example illustrating the comparison of
null
against a class:
Map<Object, Object> map = null; boolean mapIsObject = map instanceof Map;
Note, that even if the type of the map
variable is Map, and the map
variable is
compared against the Map interface, the result of the comparison is still false
. That is because
it is not the reference type that is compared against the target class or interface, but the actual type of
the referenced object. Since the map
variable has the value null
, that is what
is compared against the Map
interface in the expression map instanceof Map
.
Since null
is not an instance of Map, the expression evaluates to false
.
The Java Compiler and the instanceof Operator
Sometimes the Java compiler can detect already at compile time that an instanceof expression will always evaluate to false. Here is a Java instanceof example illustrating that situation:
String myString = "Hey"; if(myString instanceof Integer) { }
Since a Java String object can never be an instance of the Java Integer class, the Java compiler will catch this an give you an error.
Using instanceof to Downcast
One of the most common uses of the Java instanceof operator is to downcast an object of supertype to a subtype. Here is a Java instanceof example illustrating the downcast use case:
Map<Object, Object> map = new TreeMap; //... more code that is left out if(map instanceof SortedMap) { SortedMap sortedMap = (SortedMap) map; //do something with sortedMap. }
The downcasting can also be a bit more "generic" as illustrated in this instanceof example:
Object myObject = ... // get object from somewhere if(myObject instanceof String) { String myString = (String) myObject; } else if(myObject instance of Integer) { Integer myInteger = (Integer) myObject; }
Notice, that the variable referencing the object is of type Object
. That means that the actual class
of the referenced object could be pretty much any class (since all classes are subclasses of Object).
instanceof With Pattern Matching
In Java 14 the Java instanceof operator has been extended with pattern matching functionality. The functionality is still only in preview in Java 14, but there is a pretty good chance that it will stay in this or some similar form. In short, we can avoid the explicit downcast of an object when comparing it against a subclass. Here is a Java instanceof example illustrating the instanceof pattern matching functionality:
Object myObject = ... // get object from somewhere if(myObject instanceof String str) { System.out.println(str.substring(0,5)); }
Notice the str
variable after the String
class name in the instanceof expression
inside the if-statement. If the myObject
variable references an object of type String, the
str
variable will be bound to that object - cast to a String. Thus, inside the if-statement
it is no longer necessary to explicitly cast the myObject
variable to a String.
Without the pattern matching instanceof functionality, the example code would have looked like this:
Object myObject = ... // get object from somewhere if(myObject instanceof String) { String str = (String) myObject; System.out.println(str.substring(0,5)); }
Notice the explicit cast on the first line inside the if-statement.
If the instanceof expression evaluates to true, you can actually use the downcast variable directly within the same expression. Here is an instanceof example illustrating that:
Object myObject = ... // get object from somewhere if(myObject instanceof String str && str.startsWith("Hello") ) { System.out.println(str + " starts with Hello"); }
Notice how the str
variable is used within the same expression that declares it. Since the
right hand side of the expression is only evaluated if the left hand side evaluates to true
,
this cannot result in startsWith()
being called on a non-String object.
Tweet | |
Jakob Jenkov |