23 条:不要在新代码中使用原生态类型
Java 1.5 加入了泛型,即类型参数,在 1.5 之前可以将任意对象放入集合中,所以在从集合中取出来的时候都需要做强制类型转换,这就有可能导致 ClassCastException 。 1.5 加入泛型后,就得到了在编译期间检查的好处了。虽然在运行时泛型会做擦除,泛型的目的应该还是减少 ClassCastException 和一些表述上的优势。比如 List<Date> 就是存放 Date 的一个 list ,而在 1.5 以前就是一个 List ,可以放任何东西,只能程序员自己控制。
所以能不使用 rawtype 就别使用,有些地方你可能不知道该使用什么类型参数,这时应该使用通配符 <?>.
但是在类文字中必须使用 Raw type, 比如 List.class,String.class 而 List<String>.class 是不合法的。
第 24 条:消除非受检警告
尽量消除非受检警告,没有非受检警告意味着不会出现 classCastException 。如果无法消除,但是又确定类型安全的时候可以用 SuppressWarning(“unchecked”) 注解来消除,当然在该用的地方用这个注解。
第 25 条:列表优先于数组
由于数组是协变的,如下 :
Object[] ob = new Long[1];
ob[0] = "abc";
这样在编译期间不会有任何错误,但是在运行时马上就会抛出 ArrayStoreException 。
而如果你试图将一个 String 类型放入 List<Long> 中编译将不会通过。由于数组是协变的,所以数组是不能够泛型化的。
总的来说就是除非必要,都应该优先考虑用列表而不是数组。
第 26 条 : 优先考虑泛型
尽可能的将一些可能持有对象的类编写为泛型,避免在使用这些类的时候做类型转换。
第 27 条:优先考虑泛型方法
应该尽量确保调用方法时不需要做类型转换,所以尽量将方法泛型化。
第 28 条 : 利用有限制通配符来提升 API 的灵活性
有限制通配符是指 ? extends E,? super E. 第一个是指任何 E 的子类,第二个指任何 E 的父类。什么时候用哪个呢,有个助记符可以让你记住 PECS – producer extends consumer super.
利用这条原则来编写有限制的通配符。所有的 comparator 和 comparable 都是 consumer ,在有 Comparable<T> 时都可以考虑 Comparable<? super T>.
第 29 条:优先考虑异构安全的类型容器
jdk 里面的容器在有类型参数的情况下指允许放入参数类型的实例,但你可以编写一个以 Class<T> 为 key , value 为该 class 对应实例的类来存放不同类型的实例,这个就是异构。
如下示例代码:
package com.andyjiang.generic;
public interface Favorites {
public <T> void putFavorite(Class<T> clazz,T instance);
public <T> T getFavorte(Class<T> clazz);
}
package com.andyjiang.generic.impl;
import java.util.HashMap;
import java.util.Map;
import com.andyjiang.generic.Favorites;
public class FavoritesImpl implements Favorites {
private Map<Class<?>,Object> favoriteMap = new HashMap<Class<?>,Object>();
public <T> void putFavorite(Class<T> clazz, T instance) {
this.favoriteMap.put(clazz, instance);
}
public <T> T getFavorte(Class<T> clazz) {
// TODO Auto-generated method stub
return clazz.cast(this.favoriteMap.get(clazz));
}
}