In your code example
class SuperSample { } class Sample extends SuperSample { } ... ArrayList<Sample> sList = new ArrayList<Sample>(); Object o = sList; ArrayList<SuperSample> ssList = (ArrayList<SuperSample>)o;
Shouldn't a ClassCastException on the last line?
Not. This exception is thrown by the JVM when it detects incompatible types that are run at run time. As others have noted, this is due to the erasure of common types. That is, common types are known only to the compiler. At the JVM level, variables are of type ArrayList (generated styles), so there is no ClassCastException .
Instead of assigning an intermediate local variable of type Object , a shorter way to do this assignment is to pass through raw:
ArrayList<SuperSample> ssList = (ArrayList)sList;
where the "raw" type is the erased version of the generic type.
Should there be additional mechanisms to prevent adding an invalid object to the list?
Yes there is. The first mechanism is checking compilation time. In your own answer, you found the right place in the Java Language Specification, where it describes heap pollution , which is the term for an invalid object that has a place in the list. Quote from this section, bottom to bottom,
If an operation that requires an immediate compilation warning is not performed, and there is no unsafe smoothing of array variables with unrecoverable element types, then heap contamination cannot occur.
So, the mechanism you are looking for is in the compiler, and the compiler notifies you of this through compilation warnings. However, you disabled this mechanism using the @SuppressWarnings annotation. If you want to remove this annotation, you will receive a compiler warning on the violation line. If you absolutely want to prevent heap pollution, do not use @SuppressWarnings and add the -Xlint:unchecked -Werror options to your javac command line.
The second mechanism is runtime verification, which requires the use of one of the tested shells. Replace sList initialization as follows:
List<Sample> sList = Collections.checkedList(new ArrayList<Sample>(), Sample.class);
This will cause a ClassCastException be thrown at the point where SuperSample added to the list.