Arrays:
- covariant: if Sub is a subtype of Super, then Sub[ ] is a subtype of Super[ ]
- reified: arrays know and enforce their element types at runtime
Generics:
- invariant: two distinct types Type1 and Type2, List<Type1> is neither a subtype nor a supertype of List<Type2>
- erasure: enforce type constraints only at compile time and discard(or erase) element type information at runtime (这也是为什么generics能和以前没有generics的legacy code很好融合的原因)
// Fails at runtime for arrays
Object[] objectArray = new Long[1];
objectArray[0] = "I don't fit in"; // Throws ArrayStoreException
由于这些差异,所以Arrays和Generics无法很好的融合,it is illegal to create an array of a generic type, a parameterized type, or a type paramter.
new List<E>[ ], new List<String>[ ], new E[ ] - generic array creation errors at compile time
Prefer List<E> in preference to the array type E[ ]
interface Function<T>{
T apply(T arg1, T arg2);
}
// Naive generic version of reduction
static <E> E reduce(List<E> list, Function<E> f, E initVal){
E[] snapshot = (E[])list.toArray(); // cast Object[] to E[], you ensure compiler that the oject in the array is of type E instance
E result = initVal;
for(E e : snapshot)
result = f.apply(result, e);
return result;
}
// this is unsafe
static <E> E reduce(List<E> list, Function<E> f, E initVal){
E[] snapshot = (E[])list.toArray();
Object[] backdoor = snapshot; // backdoor reference the array type of Object during runtime
backdoor[0] = "String" // Okay to put String in array of Object type
E result = initVal;
for(E e : snapshot) // ClassCastException at runtime
result = f.apply(result, e);
return result;
}
// Revised version, use list instead of array
static <E> E reduce(List<E> list, Function<E> f, E initVal){
List<E> snapshot
synchronized(list){
snapshot = new ArrayList<E>(list);
}
E result = initVal;
for(E e : snapshot)
result = f.apply(result, e);
return result;
}
总结:Arrays provide runtime type safety but not compile-time type safety and vice versa for generics. If you find yourself mixing them and getting compile time errors or warnings, your first impulse should be to replace the arrays with lists.