We’ve now talked about relationships between generic types and even between generic types and raw types. But we haven’t brought up the concept of a cast yet. No cast was necessary when we interchanged generics with their raw types. Instead, we just crossed a line that triggers unchecked warnings from the compiler:
Listlist=newArrayList<Date>();List<Date>dl=list;// unchecked warning
Normally, we use a cast in Java to work with two types that could be
assignable. For example, we could attempt to cast an Object to a Date because it is plausible that the Object is a Date value. The cast then performs the check at
runtime to see if we are correct. Casting between unrelated types is a
compile-time error. For example, we can’t even try to cast an Integer to a String. Those types have no inheritance
relationship. What about casts between compatible generic types?
Collection<Date>cd=newArrayList<Date>();List<Date>ld=(List<Date>)cd;// Ok!
This code snippet shows a valid cast from a more general Collection<Date> to a List<Date>. The cast is plausible here
because a Collection<Date> is
assignable from and could actually be a List<Date>. Similarly, the following cast
catches our mistake where we have aliased a TreeSet<Date> as a Collection<Date> and tried to cast it to a
List<Date>:
Collection<Date>cd=newTreeSet<Date>();List<Date>ld=(List<Date>)cd;// Runtime ClassCastException!ld.add(newDate());
There is one case where casts are not effective with generics, however, and that is when we are trying to differentiate the types based on their parameter types:
Objecto=newArrayList<String>();List<Date>ld=(List<Date>)o;// unchecked warning, ineffectiveDated=ld.get(0);// unsafe at runtime, implicit cast may fail
Here, we aliased an ArrayList<String> as a plain Object. Next, we cast it to a List<Date>. Unfortunately, Java does not
know the difference between a List<String> and a List<Date> at runtime, so the cast is
fruitless. The compiler warns us of this by generating an unchecked
warning at the location of the cast; we should be aware that when we try
to use the cast object later, we might find out that it is incorrect.
Casts on generic types are ineffective at runtime because of erasure and
the lack of type information.