java泛型中的几种通配符
1、什么是泛型
java泛型是在JDK5的时候引入的特性,泛型给java带来了编译时类型的安全检查,清除了强制类型转换,包括有一些潜在的性能上的收益,总体,泛型更加约束了参数的类型,检查了运行错误概率。
2、泛型中有哪些符号
泛型中有很多通配符,大概有以下这些
- T 代表具体的一个java类型
- E 代表Element
- K java键值中的key
- V kava键值对中的value
- ?表示不确定的java类型
解释一些不好理解的
2.1、?无界通配符
<?>
对于不关心或者不确定实际要操作的类型,可以使用无限制通配符,表示可以持有任何类型。
<? extends YourClass>
上界通配符,使用extends 关键字声明,表示参数化的类型必须是所制定的类型或者是这个类型的子类。
<? super YourClass>
下界通配符,使用super来声明,表示参数化的类型可能是所制定的类型或者是所制定的类型的父类,甚至是Object。
2.2、T 具体类型
<T>
代表了一个具体的类型,通常用来做泛型类的和泛型方法的定义,我们可以通过这个通配符来保证泛型参数的一致性,比如
public <T extend Number> void test(List<T> dest,List<T> src);
此时如果生命的参数的内容是String,在编译的时候就会报错。
2.3、? 和 T 的区别
1、常用的一些场景区别,比如集合
List<T> list = new ArrayList<T>();
# 这种使用方法就没有任何意义
List<?> list = new ArrayList<?>();
2、我们对T是可以操作的 ,比如
T t = operate()
# 不可以
? car = operate();
3、 T可以做多重限定 ,但是? 因为是无界 所以不能多重边界限定
比如
public class MultiLimit implements MultiLimitInterfaceA ,MultiLimitInterfaceB {
public static <T extends MutiLimitInterfaceA & MultiLimitInterfaceB> void test(T t){
}
}
使用 & 符号设定多重边界(Multi Bounds),指定泛型类型 T 必须是 MultiLimitInterfaceA 和 MultiLimitInterfaceB 的共有子类型,此时变量 t 就具有了所有限定的方法和属性.
4、对于java编译器来讲,T会推断成具体的类型,但是? 推断成未知类型,这样也对应了上诉说的第二点,以为java编译器只能操作具体类型,不能操作未知类型。
5、Class<T> Class<?>
的区别
在反射场景下,我们一般使用强制类型转换来接受反射生成的实例,但其实可以这样做
public static <T> T createInstance(Class<T> clazz) throws IllegalAccessException , InstantiationException {
return clazz.newInstance();
}
当在进行实例化的时候,必须指定类型,这样在编译的时候就可以进行类型检查、
String str = createInstance(Integer.class); 检查失败了
String str = createInstance(String.class); 检查通过
但是当我们在声明属性的时候,T就没啥用了,如下
private Class<T> clacc; //编译不通过
private Class<?> claee; // 编译通过