effective Java第5章-泛型
本文章是自己看完effective Java第5章后的一点笔记,看完后觉得自己以前基本就是一个不晓得泛型是啥的人。
有了泛型,可以告诉编译器的每个集合中接受哪些对象类型,编译器会自动在插入时进行转换,并在编译时告诉你是否插入了错误的对象。
不要在新代码中使用原生态的类型
意思为不在代码中写
List list = new ArrayList()
上面的代码为原生态类型,在1.5版本前这样写是可以加入不同类型的对象,但是在取出时,强转往往会出错。错误嘛,越早发现越好,最好编译期间就发现,不然就是一颗雷。那为什么有了泛型后,在创建容器对象时制定类型就行了呢?泛型到底干了什么呢?
泛型编译时强化他们的类型信息,并在运行时擦除,在编译时会检查其元素类型信息,但在运行时丢弃其元素类型信息。
于是编译期间就能够发现是否插入了不符合类型要求的对象(其子类,会自动转为父类,编译器会帮你进行装换),还有一点很重要,** List< String >是List的子类型,但不是List< Object >的子类型**。
泛型中的"?",为无限制的类型通配符,读做每个类型的集合。表示任意类型的集合都可以,但不能将任何元素(除了null)加入Collecion<?>。
static int test(Set<?> s1, Set<?> s2){
int result = 0;
for(Object o : s1){
if( s2.contains(o) ){
result++;
}
}
return result;
}
public static void main(String[] args) {
Set<String> s1 = new LinkedHashSet<>();
Set<Object> o1 = new LinkedHashSet<>();
test(s1,o1);
}
消除非受检警告
意思就是尽可能的减少警告,如果遇到了不可能发生错误的警告代码可以使用@SuppressWarning("unchecked")注解来禁止这条警告。但是始终应该在最小范围内使用@SuppressWarning("unchecked")注解。
列表优先于数组
列表与数组的区别
-
数组是协变得,即如果sub是super的子类型,则sub[]是super[]的子类型,而列表是不可变的list与 list
没有什么关联。 Object[] objects = new Long[1]; objects[0] = "asdf,zxc"; 以上在运行时才会报错 List<Object> objets2 = new ArrayList<Long>; objects2.add("asdf"); 以上代码编译期间会报错
-
数组是具体化的,因此数组会在运行时才知道并检查他的类型,而泛型是擦除的来实现的。因此泛型只在编译时强化他们的类型信息,并在运行时丢弃(或擦除)他们的元素类型信息。擦除是使泛型可以与没有使用泛型的代码随意进行使用。
因为前面的2个原因所以数组与泛型不能共用 new List
书中的建议是:当你发现自己将数组与列表混合使用,并得到了编译时的警告或者错误时,应该用列表代替数组
优先考虑泛型与泛型方法
泛型与泛型方法都更加便于在编译期间发现问题,且使用性更加强大
利用有限制通配符来提升API的灵活性
什么是有限制通配符呢?
Collection<? extends E>();
Collection<? super E>();
因为泛型不是协变得,于是很多时候将其子类的集合传入会报错,此时就可以使用有限制通配符来解决这个问题。
书中还提出了一个很好的观点PECS表示producer-extends,consumer-super,意思就是对于消费集合中的元素的也就是使用集合中的元素的使用super,往集合中添加元素的,extends更加好。详细解释更建议看书