Reputation: 11146
Following instanceof
operator is working fine, when I type cast string to Object.
However, Without typecasting it is failing to compile.
public class Test {
public static void main(String[] args) {
boolean b1 = "abc" instanceof Integer; // Compilation fails
boolean b2 = ((Object) "abc") instanceof Integer; // Works fine
}
}
My question is why compiler is rejecting the first one b1
but allowing the second one b2
Upvotes: 0
Views: 163
Reputation: 718788
JLS 15.20 and 15.20.2 state this:
RelationalExpression: ... RelationalExpression instanceof ReferenceType
If a cast of the
RelationalExpression
to theReferenceType
would be rejected as a compile-time error (§15.16), then theinstanceof
relational expression likewise produces a compile-time error. In such a situation, the result of the instanceof expression could never be true.
In your first example expression ("abc" instanceof Integer
) "abc"
(a String
) cannot be cast to Integer
. Therefore the instanceof
expression is a compilation error.
In your second example expression (((Object) "abc") instanceof Integer
), the left operand has type Object
. In some cases, an Object
may be an Integer
. Therefore the left-hand operand can be cast to the right-hand type. Therefore the instanceof
is allowed.
It is worth noting that the JLS is only concerning itself with the compile-time types of the expressions. In the second example, we can easily deduce that the run-time type of the left hand operand is always String
and the expression will always evaluate to false
. But the JLS rules don't classify this "mistake" as a compilation error.
Upvotes: 2
Reputation: 140318
Because you've casted "abc"
to Object
, the compiler treats ((Object) "abc")
the same as any other expression of Object
type.
As such, it thinks that it could contain any Object
(or null). The compiler doesn't deeply inspect the expression to determine a more specific type.
You can also write:
Object obj = "abc";
boolean b2 = obj instanceof Integer;
It's basically the same.
It stops you writing "abc" instanceof Integer
because both String
and Integer
are classes, and they are unrelated, so a String
can never be an instance of an Integer
. (It would allow "abc" instanceof List
, because List
is an interface, and it doesn't consider the final-ness of a class, and assumes there might be a subclass of String
that could implement List
).
In a sense, casting is you telling the compiler that you know more than it does. Although the compiler is able to push back in very basic cases where it can determine that you are doing something nonsensical, it largely gets out of the way and trusts you (in a "on your head be it" kind of way).
Upvotes: 5
Reputation: 17
Instanceof can only be used between parent and child classes
the first one "abc" is String type not Integer.
but the second one ((Object) "abc") is Object type, Integer is a child of Object
Upvotes: 0