泛型,即“参数化类型”
泛型只在编译阶段有效
List<String> stringArrayList = new ArrayList<String>();
List<Integer> integerArrayList = new ArrayList<Integer>();
Class classStringArrayList = stringArrayList.getClass();
Class classIntegerArrayList = integerArrayList.getClass();
if(classStringArrayList.equals(classIntegerArrayList)){
Log.d("泛型测试","类型相同");
}
泛型类
public class Test<T> implements ITest<T>{
private T key;
public Test(T key) {
this.key = key;
}
@Override
public T getKey(){
return key;
}
}
泛型接口
public interface ITest<T> {
public T getKey();
}
将泛型理解为一种模板,将类型做参数传入,传入后可调用传入类型的方法
向上转型:Test<T>可转为ITest<T>(但Test<Number>与Test<Integer>不可)
ITest iTest=new Test<String>("test");
泛型方法
public <T> T test(T t) {
return t;
}
<T>:声明为泛型方法
T:返回值
T可随便写
麻烦
虚拟机将泛型<T>视为Object对象(这也导致了int这些基本类型不可用,欲获取类型亦相同),在编写泛型方法时,我们只能使用Object的相关方法,尽管我们欲使用的全是某个类的子类
解决
使用上界通配符,例<? extends Number>,通过更严格的限制获取更高的权限,最少是Number(故实现限制>=接口限制)
在这种情况中可get入参,不可set入参
例 Double,Integer 相对 Number
Number 内部 = Integer 入参;可转(get方法)
Integer 入参 = Number 内部;不可(set方法)
故可以通过这种方法,限制set
同样有<? super Integer>
Integer 内部 = Number 入参;不可(get方法)
Number 入参 =Interger 内部;可转(set方法)
故可以通过这种方法,限制get
-
<? extends T>
允许调用读方法T get()
获取T
的引用,但不允许调用写方法set(T)
传入T
的引用(传入null
除外); -
<? super T>
允许调用写方法set(T)
传入T
的引用,但不允许调用读方法T get()
获取T
的引用(获取Object
除外);
泛型【T】
根据泛型使用的位置,即使用在类(Class),属性(Field)和方法(Method)的不同位置,可以将泛型的用法总结为以下几种:
1.泛型类。在类名后添加泛型标识(<T...>),用于表示该类持有的一种类型。
2.泛型属性。泛型属性必须结合泛型类使用,用于接收泛型类持有的类型T。
3.泛型方法。在方法的返回值前声明泛型(<T extends 父类名>),该泛型是对该方法的参数T的一种限定。
通配符【?】
通配符代表的是一种未知的类型,常用在方法上(注意与泛型方法的区别,其不需要在方法的返回类型前声明。
参考https://www.cnblogs.com/yanggb/p/10961968.html
泛型和通配符最根本的区别就是Java编译器会把泛型【T】推断成具体类型,而把通配符【?】推断成未知类型。