[Effective Java] Item 25: Prefer lists to arrays

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.

上一篇:linux常用命令


下一篇:KubeSphere 日志备份与恢复实践