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.