Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cast to generic type (T) is never checked by the compiler?

static <T> void f1(Base arg1, T arg2) {
    T loc = (T) arg1; // why Derived is "kind of cast" to String?
    System.out.println(loc.getClass().getName()); // would print: Derived
}

f1(new Derived(), "sdf");  // T is String - inferred from arg2

class Base { }

class Derived extends Base { }

Am I correct in my thoughts: writing cast (T) means "compiler cannot and is not going to check this cast anyway". At compile-time the compiler does not know what arg2 would be (and it could be anything), so compiler cannot rule out that the cast could work and has to trust the programmer. Thus this cast is just never checked at compile time. In runtime local var declaration looks like Object loc = arg1; (after type erasure). So everything works fine just because compiler never cares about this (T) cast?

P.S: My research: this, and this. This is also very interesting ("casting primitive to generic": (T) true) My question is more clearly pinpointed on the problem, the question is also about whether the cast (T) checked by the compiler and there are no distractions in the code sample in question.

like image 803
Code Complete Avatar asked Oct 17 '22 03:10

Code Complete


1 Answers

This is covered in JLS Sec 5.5.1:

Given a compile-time reference type S(source) and a compile-time reference type T (target), a casting conversion exists from S to T if no compile-time errors occur due to the following rules.

...

If T is a class type, then either |S| <: |T|, or |T| <: |S|. Otherwise, a compile-time error occurs.

...

If T is a type variable, then this algorithm is applied recursively, using the upper bound of T in place of T.

So the compiler is using Object in place of T, and thus it considers the cast legal.

like image 159
Andy Turner Avatar answered Nov 15 '22 07:11

Andy Turner