读书笔记:Effective Java, Second Edition-5章
Item 23: Don’t use raw types in new code
带参数泛型提供了安全类型检查,自动类型转换的便利,提倡使用。
raw type指没有指明类型的如List
List<String> 是 List的子类 但不是 List<Object>的子类,ArrayList<Object>才是List<Object>的子类。
List.class,String[].class, and int.class 合法,但 List<String>.class and List<?>.class不合法。
instance操作符只能使用Raw Type (o instanceof Set) √ , (o instanceof Set<?>) ×
Set<Object> is a parameterized type representing a set that can contain objects of any type,
Set<?> is a wildcard type representing a set that can contain only objects of some unknown type, 无法使用
Set is a raw type, which opts out of the generic type system.
The first two are safe and the last is not.
Term
Example
Parameterized type
List<String>
Actual type parameter
String
Generic type
List<E>
Formal type parameter
E
Unbounded wildcard type
List<?>
Raw type
List
Bounded type parameter
<E extends Number>
Recursive type bound
<T extends Comparable<T>>
Bounded wildcard type
List<? extends Number>
Generic method
static <E> List<E> asList(E[] a)
Type token
String.class
Item 24: Eliminate unchecked warnings
消灭warning……
Item 25: Prefer lists to arrays
数组是协变的,if Sub is a subtype of Super, then the array type Sub[] is a subtype of Super[].
如此相反的是:Generics, by contrast, are invariant: for any two distinct types Type1 and Type2, List<Type1> is neither a subtype nor a supertype of List<Type2>
泛型的类型更强
不能建立泛型数组,因为需要保证泛型的类型安全【略】
总体来说就是,数组和泛型结合的不是很好,如果你碰到这种情况,使用列表代替数组。
Item 26: Favor generic types
泛型数组的解决方案(泛型中不得不用到数组的情况):
1:字段类型是T[],使用Object数组转换
private E[] elements;
// The elements array will contain only E instances from push(E).
// This is sufficient to ensure type safety, but the runtime
// type of the array won't be E[]; it will always be Object[]!
@SuppressWarnings("unchecked")
public Stack() {
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}
2:字段类型是Object数组,每次取数组元素时转换
// Appropriate suppression of unchecked warning
public E pop() {
if (size==0)
throw new EmptyStackException();
// push requires elements to be of type E, so cast is correct
@SuppressWarnings("unchecked")
E result = (E) elements[--size];
elements[size] = null; // Eliminate obsolete reference
return result;
}
Item 27: Favor generic methods
Item 28: Use bounded wildcards to increase API flexibility
PECS 原则:if a parameterized type represents a T producer, use <? extendsT>;if it represents a T consumer, use <? superT>.
// Wildcard type for parameter that serves as an E consumer
public void popAll(Collection<? super E> dst) {
while (!isEmpty())
dst.add(pop());
}
// Wildcard type for parameter that serves as an E producer
public void pushAll(Iterable<? extends E> src) {
for (E e : src)
push(e);
}
Item 29: Consider typesafe heterogeneous containers
容器里面多种类型的情况:
// Typesafe heterogeneous container pattern - implementation
public class Favorites {
private Map<Class<?>, Object> favorites = new HashMap<Class<?>, Object>(); //以Class<?>作为键达到多种类型的目的。注意Class<?>这个特殊的形式参照Item23.
public <T> void putFavorite(Class<T> type, T instance) {
if (type == null)
throw new NullPointerException("Type is null");
favorites.put(type, instance);
}
public <T> T getFavorite(Class<T> type) {
return type.cast(favorites.get(type));//将Object安全的转为了绑定类型