Search code examples
javagenericstype-conversionwarningsjavac

Where is the definition of unchecked warning for Object to generic type conversion?


JLS 5.1.9 defines the unchecked conversion as follows :

Let G name a generic type declaration with n type parameters.

There is an unchecked conversion from the raw class or interface type G to any parameterized type of the form G<T1,...,Tn>.

There is an unchecked conversion from the raw array type G[] to any array type type of the form G<T1,...,Tn>[].

Use of an unchecked conversion causes a compile-time unchecked warning unless G<...> is a parameterized type in which all type arguments are unbounded wildcards, or the unchecked warning is suppressed by the SuppressWarnings annotation

As far as I can understand it says that unchecked conversion occurs if you cast a raw type to a generic type with bounded type parameters. then why following code generates a unchecked warning:

public class DoubleStar{

    public static void print(Object object){
       ((A<String>)object).print();
    }

    public static void main(String[] args){
        print(new Object());
    }
}

class A<T>{
    public void print(){
        System.out.print("HELLO");
    }
}

As Object is not a raw type (AFAIK) why should the above code generate a unchecked cast warning and where this behaviour is defined ?


Solution

  • You're looking at the wrong section which is why it doesn't seem to make sense in the context of your example.

    The warning you have is an unchecked cast. You are looking at the section on unchecked conversions (related).

    See 5.5.2 "Checked Casts and Unchecked Casts"

    A cast from a type S to a type T is statically known to be correct if and only if S <: T (§4.10).

    A cast from a type S to a parameterized type (§4.5) T is unchecked unless at least one of the following conditions holds:

    • S <: T
    • All of the type arguments (§4.5.1) of T are unbounded wildcards
    • T <: S and S has no subtype X other than T where the type arguments of X are not contained in the type arguments of T.

    A cast from a type S to a type variable T is unchecked unless S <: T.

    An unchecked cast from S to T is completely unchecked if the cast from |S| to |T| is statically known to be correct. Otherwise, it is partially unchecked.

    An unchecked cast causes a compile-time unchecked warning, unless suppressed by the SuppressWarnings annotation (§9.6.3.5).

    A cast is checked if it is not statically known to be correct and it is not unchecked.

    If a cast to a reference type is not a compile-time error, there are several cases:

    • The cast is statically known to be correct.

    No run-time action is performed for such a cast.

    • The cast is a completely unchecked cast.

    No run-time action is performed for such a cast.

    • The cast is a partially unchecked cast.

    Such a cast requires a run-time validity check. The check is performed as if the cast had been a checked cast between |S| and |T|, as described below.

    • The cast is a checked cast.

    Such a cast requires a run-time validity check. If the value at run time is null, then the cast is allowed. Otherwise, let R be the class of the object referred to by the run-time reference value, and let T be the erasure (§4.6) of the type named in the cast operator. A cast conversion must check, at run time, that the class R is assignment compatible with the type T, via the algorithm in §5.5.3.

    Note that R cannot be an interface when these rules are first applied for any given cast, but R may be an interface if the rules are applied recursively because the run-time reference value may refer to an array whose element type is an interface type.