Florian Reisinger Florian Reisinger - 7 days ago 5
Java Question

Cast to Generic type java (why unchecked)

I wonder why the following cast is unchecked:

== Update 1 ==

I know that we have type erasure at runtime. Mind the input parameter is a

ArrayList
and not some random list.
ArrayList
implements
List
and
RandomAccess
. I know this cast will not work with
LinkedList
or
MySpecialArrayList
. but the parameter of this method forbids that. I know (until people remove
List
or
RandomAccess
from
ArrayList
the cast will not fail at runtime, but why is the cast unchecked?

== End update 1 ==

private static <L extends List<GenericTokenType<?>> & RandomAccess> L castArrayList(ArrayList<GenericTokenType<?>> instance) {
return (L) instance;
}


I simplified this to [still warning]

private static <L extends List> L castArrayList(ArrayList instance) {
return (L) instance;
}


and [no warning]

private static List castArrayList(ArrayList instance) {
return (List) instance;
}


Why does this not work.
L
is a
List
(not the runtime type, but the compiler should get that.

To rephrase the question: Why doesn't it work with a generic parameter return type? Thanks

Answer

L will be erased to List, since that is the lower bound. However, the uncheckedness comes from the fact that L can technically be a subclass of List, but due to type erasure, only a cast to (at most) List can be performed. The actual cast will be performed later when the concrete type is available.

You can see this nicely in bytecode too:

  public static void main(java.lang.String[]) throws java.lang.Exception;
    Code:
       0: new           #2  // class java/util/ArrayList
       3: dup
       4: invokespecial #3  // Method java/util/ArrayList."<init>":()V
       7: invokestatic  #4  // Method castArrayList:(Ljava/util/ArrayList;)Ljava/util/List;
      // Cast is done here, after returning
      10: checkcast     #2  // class java/util/ArrayList
      13: astore_1
      14: return

  public static <L extends java.util.List> L castArrayList(java.util.ArrayList);
    Code:
       0: aload_0
       // No 'checkcast' here
       1: areturn