I have the following Java code that uses a local class.
import java.util.Arrays;
public class X<T> {
void m() {
class Z {}
for (Object o : Arrays.asList(1, 2, 3))
if (o instanceof Z) {}
}
}
It does not compile with the following error message:
X.java:8: error: illegal generic type for instanceof
if (o instanceof Z) {}
^
1 error
I understand that the local class Z
inherits the generic type signature of X<T>
, being an inner class. The same kind of compilation error appears in this example, where Z
is not local, but still inner:
import java.util.Arrays;
public class X<T> {
class Z {}
void m() {
for (Object o : Arrays.asList(1, 2, 3))
if (o instanceof Z) {} // Compilation error
}
}
It can be worked around either by making Z
non-inner / static:
import java.util.Arrays;
public class X<T> {
static class Z {}
void m() {
for (Object o : Arrays.asList(1, 2, 3))
if (o instanceof Z) {} // Compiles now
}
}
Or by qualifying X.Z
:
import java.util.Arrays;
public class X<T> {
class Z {}
void m() {
for (Object o : Arrays.asList(1, 2, 3)) {
if (o instanceof X.Z) {} // Compiles now
if (o instanceof X<?>.Z) {} // Also
}
}
}
But how can I qualify a local class, or work around this limitation, without changing the local class itself?
To me this seems to be an oversight or limitation in the Java language and I do not think it is possible.
The referenced type in an instanceof
expression must be reifiable according to JLS 4.7, meaning that it must be expressed as a reifiable type by its fully qualified name. At the same time, JLS 6.7 states that local classes do not have a fully qualified name, they can therefore not be expressed as reifiable.
If you declare Z as generic, the instanceof
operator treats Z
as a raw type where all generic properties to it - in this case the enclosing class - are considered raw as well. (Similar to a generic methods of a raw type being considered as raw despite any generic signature. This is a measure to retain backwards compatiblity of type generification.) Since any raw type is reifiable, declaring Z to be generic will compile.