请不要在新代码中使用原生态类型
首先原生态类型是指List,区别于List<String>、List<Object>,原生态类型没有经过类型检查,并且在代码中会出现请使用List<E>来替代List。
其次原生态类型是不安全的,因为所有类型的值都可以放到原生态类型中,这很容易破坏集合的类型约束条件。
无限制通配类型:在Set后面加上<?>,这与原生态类型本质区别就是,它经过集合类型检查所以它是安全的。
注:无限制通配类型只能用来读取,如果进行add操作,编译时会报错。
另外,有2种需要使用原生态类型的情况
- 在类文字中必须使用原生态类型。例如:Class<List> clazz = List.class;
- 在使用instanceof时不需要在集合后面加泛型。例如: o instanceof Set;
消除非受检警告
非受检警告是非常重要的,如果存在这些警告,就很有可能抛出ClassCastException这样的异常,所以一定要消除这些警告,如果这些警告无法被消除,那么确保这个声明是类型安全的,可以使用@SuppressWarnings(“unchecked”)来禁止这条警告。
@SuppressWarnings(“unchecked”)它的作用是消除非受检警告,它可以使用在任意声明变量的地方,也可以使用在类的头部。但是我们永远都不要将它写在类的头部,因为这会忽略掉很重要的警告。
列表优先于数组
数组和泛型有着非常不同的类型规则。数组是协变且可以具体化的;泛型是不可变的且可以被擦除的。因此,数组提供了运行时的类型安全,但是没有编译时的类型安全,反之,对于泛型也一样。一般来说,数组和泛型不能很好地混合使用。如果你发现自己将它们混合起来使用,并且得到了编译时错误或者警告,你的第一反应就应该是列表代替数组。
优先考虑泛型
首先想一个问题,泛型和非泛型有什么区别?
泛型就是形如List<E>这样的泛型集合,非泛型就是具体的类型集合形如List<String>,那么泛型的好处就是:类型安全,性能高,使用方便(不需要手动强制转换)。
下面是栈(Stack)的一个使用具体类型的例子:
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULR_INITIAL_CAPACITY = 16;
public Stack() {
elements = new Object[DEFAULR_INITIAL_CAPACITY];
}
public void push(Object o){
ensureCapacity();
elements[size++] = o;
}
public Object pop(){
if(elements.length == 0)
throw new EmptyStackException();
@SuppressWarnings("unchecked")
Object o = elements[--size];
elements[size] = null;
return o;
}
public void ensureCapacity(){
if(elements.length == size)
elements = Arrays.copyOf(elements, size * 2 + 1);
}
}
给这个例子强化一下,使用泛型代替Object:
public class Stack<E> {
private Object[] elements;
private int size = 0;
private static final int DEFAULR_INITIAL_CAPACITY = 16;
public Stack() {
elements = new Object[DEFAULR_INITIAL_CAPACITY];
}
public void push(E o){
ensureCapacity();
elements[size++] = o;
}
public E pop(){
if(elements.length == 0)
throw new EmptyStackException();
@SuppressWarnings("unchecked")
E o = (E) elements[--size];
elements[size] = null;
return o;
}
public void ensureCapacity(){
if(elements.length == size)
elements = Arrays.copyOf(elements, size * 2 + 1);
}
}
使用泛型比使用需要在客户端代码中进行转换的类型来的更加安全,也更加容易。在设计新类型的时候,要确保它们不需要这种转换就可以使用。
优先考虑泛型方法
泛型方法就是在方法修饰符和返回值类型之间增加泛型。
优点:1.类型安全。 2.不用转换就能使用。