简体   繁体   中英

Fully qualified generics type casting error overlooked by Java compiler?

Generics are knowingly meant for stronger type checking at compile time. However, while studying the official Java tutorial, I ran into this:

However, in some cases the compiler knows that a type parameter is always valid and allows the cast. For example:

List<String> l1 = ...;
ArrayList<String> l2 = (ArrayList<String>)l1;  // OK

from http://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#cannotCast .

I've tried and tested this (which fully reflects the documentation):

List<String> l1 = new LinkedList<String>();
ArrayList<String> l2 = (ArrayList<String>)l1;  // OK

Although everything is pretty explicit (no assignment to an Object variable, no wilcarding, etc), the compiler fails to predict the runtime error that shows up afterwards:

Exception in thread "main" java.lang.ClassCastException: java.util.LinkedList cannot be cast to java.util.ArrayList

100% puzzled.

Reread the link -- it's not stating you can cast a LinkedList to an ArrayList . It's stating that you can downcast a List of String to the (presumably programmer-known) type of ArrayList of String . What they're attempting to illustrate is the difference between the generic type parameters. Their first example shows casting from a collection of Integer to a collection of Number , which is not allowed.

Typically, you cannot cast to a parameterized type unless it is parameterized by unbounded wildcards. For example:

List li = new ArrayList<>(); List ln = (List) li; // compile-time error

However, in some cases the compiler knows that a type parameter is always valid and allows the cast. For example:

List l1 = ...; ArrayList l2 = (ArrayList)l1; // OK

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM