Java has quite a few ways to compare types of objects. Most well know are:
- operator
instanceof
; - method
Class.isInstance(Object obj)
; - method
Class.isAssignableFrom(Class<?> cls)
.
The logic of the first two can be quite easily inferred based on the names. But the last one needs a bit of thinking to completely interpret it. So how to understand it once and forever?
Before moving to the last method it is important to understand how the previous two are working.
instanceof
This operator is easy to replace by a simple phrase: “… is a …“, which indicates if a concrete object is related to some group. For example, having two classical representatives of inheritance: Shape
and Circle
, the following assertions are valid:
// shape IS A shape => YES // as shape belongs to a group of shapes Assertions.assertThat(new Shape() instanceof Shape).isTrue(); // circle IS A shape => YES // as circle belongs to a group of shapes Assertions.assertThat(new Circle() instanceof Shape).isTrue(); // BUT, shape IS A circle => NO // as shape does not belong to a group of circles, it is vice versa Assertions.assertThat(new Shape() instanceof Circle).isFalse();
In fact, C# language has an equivalent of this operator, named is
.
One more good explanation of the logic of this operator can be like this: Object instanceof Type
is true
when Object
can be assigned to a variable of type Type
.
Class.isInstance(Object obj)
This method is pretty similar to the previously explained operator instanceof
. The only difference here is the order of participants: now the object acts as an argument, but the logic is the same: Type.isInstance(Object)
is true
when Object
can be assigned to a variable of type Type
.
It is quite an easy exercise to replace isInstance
with =
sign to simplify the statement: Type.isInstance(Object)
=> Type t = Object
.
// Shape shape = new Shape(); // < OK Assertions.assertThat(Shape.class.isInstance(new Shape())).isTrue(); // Shape shape = new Circle(); // < OK Assertions.assertThat(Shape.class.isInstance(new Circle())).isTrue(); // Circle circle = new Shape(); // < ERROR Assertions.assertThat(Circle.class.isInstance(new Shape())).isFalse();
Side note: condition for instanceof
is decided during the compile time, whereas for Class.isInstance(Object obj)
– runtime.
Class.isAssignableFrom(Class<?> cls)
To understand this method there can be a couple of ways.
Relation to Class.isInstance(Object obj)
In fact, there is a very simple equation exists between current and previous method: Shape.isInstance(circleObj)
== Shape.isAssignableFrom(circleObj.getClass())
but only in case when circleObj
is not null
. The first method accepts the object but the second one – type.
Assignment rule
Method Class.isAssignableFrom(Class<?> cls)
can be replaced with another simple phrase: “… can be set with …“, for example:
// Shape variable can be set with a Shape object // Shape shape = new Shape(); // < OK Assertions.assertThat(Shape.class.isAssignableFrom(Shape.class)).isTrue(); // Shape variable can be set with a Circle object // Shape shape = new Circle(); // < OK Assertions.assertThat(Shape.class.isAssignableFrom(Circle.class)).isTrue(); // Circle variable can NOT be set with a Shape object // Circle circle = new Shape(); // < ERROR Assertions.assertThat(Circle.class.isAssignableFrom(Shape.class)).isFalse();
Be First to Comment