Summary
Based on the experiences with the previous round of preview, we propose the following update:
- make
instanceofaware of the deduced type of the relational expression when the type on RHS is a primitive type.
Problem
Currently, and after the first preview, the following two examples work as expected (relevant discussion).
Short s = 42;
s instanceof int
// correctly evaluates to true, because s has static type Short
// the conversion that is safeguarded is the following: Short -> short -> int
Object o = s;
o instanceof int
// correctly evaluates to false, because o has static type Object
// the conversion that is safeguarded is the following: Object -> Integer -> int (s is of type Short so this fails)
However, javac accepts the following two with different runtime behavior:
List<Short> ls = List.of((short) 42);
switch(ls.get(0)) {
case int _ -> true;
default -> false;
}
// correctly evaluates to true,
// since an automatically generated cast is inserted with the deduced type ((Short) ls.get(0)).
ls.get(0) instanceof int
// erroneously evaluates to false, since what is executed is ls.get(0): Object instanceof int.
// instanceof should safeguard the Short -> short -> int conversion
// instead, instanceof safeguards the Object -> Integer -> int conversion (and fails).
There are two requirements here. instanceof should continue being the
precondition of safe casting and safe casting is described in Section 5.5. The
second is that switch and instanceof should expose the same behavior.
While the automatically generated cast ensures safety in terms of heap pollution in the selector expression of switch by raising a CCE, instanceof never intended to raise a CCE in case of heap pollution for the evaluation of its relational expression.
Solution
There are two alternatives:
Sharp Cast Insertion: Automatically insert a sharp cast with the deduced type to the relational expression similarly to switch.
e.g.,
(Short) ls.get(0) instanceof intThis approach would align the behavior of the new
instanceofwithswitch.In that case, an automatically generated cast would ensure that heap pollution is signaled similarly with
switch. However,instanceofwill start raising a CCE in case of heap pollution (somethinginstanceofhas traditionally avoided).Pattern-based Translation: Instead of introducing a sharp cast, use a pattern that first checks for the deduced type and then performs the instanceof test with the original RHS of the instanceof.
e.g.,
ls.get(0) instanceof Short s && s instanceof intThat retains the unwritten philosophy of
instanceofthat never throws--even in the case of heap pollution--at the expense of a more complex translation.
In the second preview we address this issue by following the second (2) option.
This maintains the philosophy of instanceof not throwing exceptions, even in
cases of heap pollution, while ensuring the correct behavior when testing
primitive types.
Specification
The JLS draft showing the exact wording for the above solutions is attached as JLS-instanceof-1.pdf
- csr of
-
JDK-8341408 Implement JEP 488: Primitive Types in Patterns, instanceof, and switch (Second Preview)
-
- Resolved
-