-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
P4
-
None
-
Affects Version/s: 26
-
Component/s: core-libs
`Class.isInstance` is equivalent to the `instanceof` type comparison operator
and it is defined in terms of the cast operation not throwing. This is on par
with the JLS specification (JLS 15.20.2 The instanceof Operator).
However, we observe that the term "assignment-compatible" is used in the
documentation of this method early on:
> * Determines if the specified {@code Object} is assignment-compatible
> * with the object represented by this {@code Class}. This method is
> * the dynamic equivalent of the Java language {@code instanceof}
> * operator. The method returns {@code true} if the specified
> * {@code Object} argument is non-null and can be cast to the
> * reference type represented by this {@code Class} object without
> * raising a {@code ClassCastException.} It returns {@code false}
> * otherwise.
From JLS 5.2 assignment compatibility refers to convertibility of an expression
under the assignment context and not the casting context:
> If the type of an expression can be converted to the type of a variable by
> assignment conversion, we say the expression (or its value) is assignable to the
> variable or, equivalently, that the type of the expression is assignment
> compatible with the type of the variable.
Under that documentation someone could erroneously understand that the following
would return true:
byte.class.isInstance((Integer) 5)
since the following assignment is allowed under the assignment context:
byte b = 5
In reality such conversion is not allowed by the casting context at all:
jshell> (Integer) b
| Error:
| incompatible types: byte cannot be converted to java.lang.Integer
| (Integer) b
In addition, the assignment context does not allow narrowing reference
conversion at all, while the casting context does:
class Animal {}
class Dog extends Animal {}
Dog d = new Dog();
Animal a = d;
jshell> Dog d = a;
| Error:
| incompatible types: Animal cannot be converted to Dog
| Dog d = a;
| ^
jshell> Dog.class.isInstance(a)
$28 ==> true
jshell> a instanceof Dog
$30 ==> true
jshell> (Dog) a
$29 ==> Dog@5f4da5c3
The documentation should refer to cast convertibility without raising a
`ClassCastException` from the beginning or more specifically by relying on the
semantics of `instanceof` and the necessary condition that avoids raising of a
CCE, for example:
> Determines if the specified Object is an instance of the type represented by
> this Class. For a class type, this means that the object that is an instance of
> that class or of some subclass of that class. For an interface type, this means
> an object that is an instance of a class that implements, directly or indirectly,
> that interface.
and it is defined in terms of the cast operation not throwing. This is on par
with the JLS specification (JLS 15.20.2 The instanceof Operator).
However, we observe that the term "assignment-compatible" is used in the
documentation of this method early on:
> * Determines if the specified {@code Object} is assignment-compatible
> * with the object represented by this {@code Class}. This method is
> * the dynamic equivalent of the Java language {@code instanceof}
> * operator. The method returns {@code true} if the specified
> * {@code Object} argument is non-null and can be cast to the
> * reference type represented by this {@code Class} object without
> * raising a {@code ClassCastException.} It returns {@code false}
> * otherwise.
From JLS 5.2 assignment compatibility refers to convertibility of an expression
under the assignment context and not the casting context:
> If the type of an expression can be converted to the type of a variable by
> assignment conversion, we say the expression (or its value) is assignable to the
> variable or, equivalently, that the type of the expression is assignment
> compatible with the type of the variable.
Under that documentation someone could erroneously understand that the following
would return true:
byte.class.isInstance((Integer) 5)
since the following assignment is allowed under the assignment context:
byte b = 5
In reality such conversion is not allowed by the casting context at all:
jshell> (Integer) b
| Error:
| incompatible types: byte cannot be converted to java.lang.Integer
| (Integer) b
In addition, the assignment context does not allow narrowing reference
conversion at all, while the casting context does:
class Animal {}
class Dog extends Animal {}
Dog d = new Dog();
Animal a = d;
jshell> Dog d = a;
| Error:
| incompatible types: Animal cannot be converted to Dog
| Dog d = a;
| ^
jshell> Dog.class.isInstance(a)
$28 ==> true
jshell> a instanceof Dog
$30 ==> true
jshell> (Dog) a
$29 ==> Dog@5f4da5c3
The documentation should refer to cast convertibility without raising a
`ClassCastException` from the beginning or more specifically by relying on the
semantics of `instanceof` and the necessary condition that avoids raising of a
CCE, for example:
> Determines if the specified Object is an instance of the type represented by
> this Class. For a class type, this means that the object that is an instance of
> that class or of some subclass of that class. For an interface type, this means
> an object that is an instance of a class that implements, directly or indirectly,
> that interface.