CSE 331: Generics
A generic class or interface declares one or more type
parameters in angle brackets after its name, and code that uses it
writes a type argument there, as in ListQueue<String>. The type
argument is a claim about every element, and javac checks it at
every call. javac confirms type safety one line at a time: on
every run, a variable refers only to objects of its declared type.
So a queue of Strings needs no cast, where a queue of
Objects needs a cast that can fail when the program runs. Inside a
generic class, the code may call on an E only the methods of
Object. A bound, as in <P extends Product>, lets the code use a
P as a Product, and a method may declare a type parameter
itself. javac does not accept a List<SaleProduct> where a
List<Product> is expected, though every SaleProduct is a
Product: the add of a list of sale products takes only a
SaleProduct, a stronger precondition, so that list is not a
behavioral subtype. Java gave arrays the other answer, and checks
each store into an array of objects when the program runs. A wildcard
asks for less: a List<? extends Product> can be read from, and its
add accepts nothing but null, and a List<? super SaleProduct>
can be added to, while an element read from it is known only to
be an Object. javac leaves the type arguments out of the code
that runs, which is called type erasure, so instanceof cannot
check one.