Duplicate :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
[Merged the description from 6717221] Consider the following program: import java.util.*; class cast { Iterable<? extends Number> x1 = null; Collection<? extends Number> x2 = (Collection<? extends Number>)x1; // javac generates a warning here } The JLS seems to mandate a warning (JLS 5.5) for a cast that can be considered 'statically-safe': "A cast from a type S to a parameterized type (��4.5) T is unchecked unless at least one of the following conditions hold: 1) S <: T. 2) All of the type arguments (��4.5.1) of T are unbounded wildcards. 3) T <: S and S has no subtype XT , such that the erasures (��4.6) of X and T are the same. " Here we have that: 1) S (Iterable<? extends Number>) is *not* a subtype of T (Collection<? extends Number>) 2) T's type argument (? extends Number) is *not* an unbounded wildcard 3) There are *infinite* subtypes of S of the kind J = Collection<? extends K>, with K <: Number, such that |J| == |T| Thus the JLS wants the cast to raise a warning, when there is no need. In the following program, the JLS also wants a warning and javac doesn't give one: class I1<T> {} class I2<T> extends I1<T> {} class Main { void f(I1<Integer> i1) { Object o = (I2<? extends Number>) i1; } } The code is safe and no warning is logically "necessary" because no heap pollution can result from the cast at runtime, but it is a shortcoming of the specification that it doesn't justify javac's behavior. In short, it is both a javac bug (it doesn't comply with the specification) and a specification bug (the spec should justify javac's current behavior). This area of the JLS would benefit from an overhaul. On 1/7/07, ... wrote: We issue an unchecked cast warning on this: interface I1<T> {} class GC22<T> implements I1<T> {} class A { I1<Short>[] x = null; GC22<? extends Number>[] y = (GC22<? extends Number>[])x; } but javac doesn't. Is this because the rules in JLS 5.5 about unchecked casts refer to parameterized types, and an array of a parameterized type doesn't count as a parameterized type?
|