This is a compiler bug. The compiler should give an
error message when you use instanceof with a generic type on
the right.
Thanks for the clarification, but I'm not sure that I understand what you are trying to say. Are you saying that use of instanceof with a generic type as the right-hand side operand is illegal in
all cases?
That would be in contradiction to the specification. The spec says (section 5.5, page 13):
"Type comparison can involve parameterized types. The rules of casting conversions, as defined in Section 5.4 apply."
In addition, the spec specifies the syntax of instanceof expressions and it gives examples. Perhaps I am misreading the spec, but it does not look like use of generic types in instanceof expressions is
in general illegal. I guess that's not what you were trying to say.
What exactly is the compiler bug? Only the treatment of the second instanceof expression is surprising. The compiler accepts it although it can ascertain statically that this cast can never succeed.
Collection<? extends String> ref2 = new ArrayList<String>();
boolean b = ref2 instanceof Collection<? extends Number>;
Section 5.4 rules out (for cast and instanceof expressions) whether and when an error message must be issued. It says:
"A value of type S can be cast to a parameterized type T if one of the following conditions holds:
1.) T is a subtype of S, and there are no other subtypes of S with the same erasure as T.
2.) T is a supertype of S. [ ... ]"
Applied to the example it means: a value of type ArrayList<String> can be cast (or compared) to the parameterized type Collection<? extends Number> if (1) Collection<? extends Number> is a subtype of ArrayList<String> or (2) Collection<? extends Number> is a supertype of ArrayList<String>. Since none of the conditions holds an error message must be issued.
I don't understand why the spec talks of "a
value of type S"; I would expect that the type of the reference variable would be used, not the type of the value referred to. But in the example it doesn't make a difference anyway. The type Collection<? extends String> is in no super- or subtype relationship to type Collection<? extends Number> either.
I would expect an error message. The compiler does not issue the expected message - due to a compiler bug. Is this what you are saying?
By the way, is this a compiler bug, too?
clas X<T> {
void f(T arg) { boolean b = arg instanceof T; }
}
The compiler mumbles something regarding "unexpected type, found : T, required: class or array". It looks to me as though the compiler would in general reject the use of type variables as the right-hand side operand of instanceof expressions. The spec however allows it. See the syntax productions; it permits "RelationalExpression instanceof ReferenceType" and a ReferenceType can be a TypeVariable. The compiler can only reject the instanceof expression above on the ground of section 5.4, which it can't do in this case because the static type of arg is T.