主要观点总结
本文介绍了Java泛型的相关概念,包括泛型的好处、泛型中的通配符、以及Class<T>和Class<?>的区别。文章还通过示例代码解释了上界通配符和下界通配符的使用。
关键观点总结
关键观点1: Java泛型是JDK 5中引入的新特性,提供了编译时类型安全检测机制。
泛型允许开发者在编译时检测到非法的类型,本质是参数化类型。
关键观点2: 泛型的好处是在编译时能够检查类型安全,避免运行时类型转换错误。
所有的强制转换都是自动和隐式的。
关键观点3: 通配符在泛型中常用,如T、E、K、V等,都是编码时的约定俗成,本质上没有区别。
常用的通配符如?表示不确定的java类型,T表示具体的一个java类型,K和V分别代表java键值中的Key和Value,E代表Element。
关键观点4: Class<T>和Class<?>在反射场景下有区别。
Class<T>在实例化的时候,T要替换成具体类。Class<?>是个通配泛型,主要用于声明时的限制情况。
关键观点5:
上界通配符用extends关键字声明,表示参数化的类型可能是所指定的类型或其子类。下界通配符用super进行声明,表示参数化的类型可能是所指定的类型或其父类型。
正文
-
-
-
K V (key value) 分别代表java键值中的Key Value
-
?无界通配符
我有一个父类 Animal 和几个子类,如狗、猫等,现在我需要一个动物的列表,我的第一个想法是像这样的:
List extends Animal> listAnimals
为什么要使用通配符而不是简单的泛型呢?通配符其实在声明局部变量时是没有什么意义的,但是当你为一个方法声明一个参数时,它是非常重要的。
staticintcountLegs (List extends Animal > animals ) {int retVal = 0;for ( Animal animal : animals ) { retVal += animal.countLegs(); }return retVal;}
staticintcountLegs1 (List< Animal > animals ){int retVal = 0;for ( Animal animal : animals ) { retVal += animal.countLegs(); }return retVal;}
publicstaticvoidmain(String[] args) { List dogs = new ArrayList<>(); countLegs( dogs ); countLegs1(dogs);}
当调用 countLegs1 时,就会飘红,提示的错误信息如下:
所以,对于不确定或者不关心实际要操作的类型,可以使用无限制通配符(尖括号里一个问号,即 > ),表示可以持有任何类型。像 countLegs 方法中,限定了上届,但是不关心具体类型是什么,所以对于传入的 Animal 的所有子类都可以支持,并且不会报错。而 countLegs1 就不行。
上界通配符 < ? extends E>