Overview
Generic as powerful compiler time check for typing rules for method parameters and return values. They often used for Collections for a runtime check of the elements added and the element you get back.
There are plans to improve runtime support for Generics http://tech.puredanger.com/java7#reified
The getClass() method.
Generics are a compiler feature and the compiler has no special handling for the Object.getClass() method. The upshot of this is that the runtime type is correct but the compiler type is incorrect.
Integer i = 5; Class<Integer> intClass = i.getClass(); // fails to compile! Class<Integer> intClass = (Class<Integer>) i.getClass(); // fails to compile! Class<Integer> intClass = (Class<Integer>) (Class) i.getClass(); // compiles but its really ugly. Class<Integer> intClass = (Class) i.getClass(); // compiles but its really ugly.
If part of an expression is non-generic the compiler gives up.
If an part of a generic is non-generic it gives up. There is no graceful fall back.
class Map<K,V> {
Set<Entry<K,V>> entrySet();
}
Map map = ....
Set<Entry> entries = map.entrySet(); // fails to compile as without the K,V it has no idea!
Set<Entry> entries = (Set<Entry>) map.entrySet(); // this is okay.
Map<?,?> map2 = ...
Set<Entry<?,?>> entries = map2.entrySet(); // this is okay.
Even if the a generic parameter is irrelevant to an expression, generic rules are forgotten.
List list = new ArrayList(); String[] objects = list.toArray(new String[list.size()]); // this fails because list doesn't have a generic declaration. List<?> list = new ArrayList(); String[] objects = list.toArray(new String[list.size()]); // this compiles fine as the actual element type of the list is irrelevant.
Generics are arrays.
Generics and arrays don't play well together. If the generic type is a primitive type, all bets are off.
List<String>[] lists = new List<String>[2]; // fails to compile as you cannot create an array of generic. List<String>[] lists = new List[2]; // produces a warning as you are doing an unchecked assignment. List<String>[] lists = (List<String>) new List[2]; // produces a warning as you are doing an unchecked cast.
Generics tend to upgrade primitive classes to wrapper classes, but this doesn't always work as expected.
public static <T> T[] newArray(Class<T> type, int length) {
return (T[]) Array.newInstance(type, length);
}
String[] strings = newArray(String.class, 10); // compiles and runs okay.
int[] ints = newArray(int.class, 10); // compiles but blows up at runtime. The (T[]) gets a ClassCastException.
Add Comment