Java 泛型 T,E,K,V,? 傻傻分不清?
# 前言
# 泛型带来的好处
public class GlmapperGeneric{ private T t;public void set(T t) { this.t = t; }public T get() { return t; }public static void main(String[] args) {// do nothing}/*** 不指定类型*/public void noSpecifyType(){GlmapperGeneric glmapperGeneric = new GlmapperGeneric();glmapperGeneric.set("test");// 需要强制类型转换String test = (String) glmapperGeneric.get();System.out.println(test);}/*** 指定类型*/public void specifyType(){GlmapperGenericglmapperGeneric = new GlmapperGeneric(); glmapperGeneric.set("test");// 不需要强制类型转换String test = glmapperGeneric.get();System.out.println(test);}}
# 泛型中通配符
常用的 T,E,K,V,?
?表示不确定的 java 类型 T (type) 表示具体的一个java类型 K V (key value) 分别代表java键值中的Key Value E (element) 代表Element
?无界通配符
List<Animal> listAnimals
List extends Animal> listAnimals
static int countLegs (List extends Animal > animals ) {int retVal = 0;for ( Animal animal : animals ){retVal += animal.countLegs();}return retVal;}static int countLegs1 (List< Animal > animals ){int retVal = 0;for ( Animal animal : animals ){retVal += animal.countLegs();}return retVal;}public static void main(String[] args) {Listdogs = new ArrayList<>(); // 不会报错countLegs( dogs );// 报错countLegs1(dogs);}

上界通配符 < ? extends E>
上界:用 extends 关键字声明,表示参数化的类型可能是所指定的类型,或者是此类型的子类。
如果传入的类型不是 E 或者 E 的子类,编译不成功 泛型中可以使用 E 的方法,要不然还得强转成 E 才能使用
privateextends A, E extends B> E test(K arg1, E arg2){E result = arg2;arg2.compareTo(arg1);//.....return result;}
类型参数列表中如果有多个类型参数上限,用逗号分开
下界通配符 < ? super E>
下界: 用 super 进行声明,表示参数化的类型可能是所指定的类型,或者是此类型的父类型,直至 Object
privatevoid test(List super T> dst, List src) {for (T t : src) {dst.add(t);}}public static void main(String[] args) {Listdogs = new ArrayList<>(); Listanimals = new ArrayList<>(); new Test3().test(animals,dogs);}// Dog 是 Animal 的子类class Dog extends Animal {}
?和 T 的区别

// 可以T t = operate();// 不可以?car = operate();
区别1:通过 T 来 确保 泛型参数的一致性
// 通过 T 来 确保 泛型参数的一致性publicextends Number> voidtest(Listdest, List src) //通配符是 不确定的,所以这个方法不能保证两个 List 具有相同的元素类型public voidtest(List extends Number> dest, List extends Number> src)

GlmapperGeneric<String> glmapperGeneric = new GlmapperGeneric<>();List<String> dest = new ArrayList<>();List<Number> src = new ArrayList<>();glmapperGeneric.testNon(dest,src);
区别2:类型参数可以多重限定而通配符不行

区别3:通配符可以使用超类限定而类型参数不行
T extends A
? extends A? super A
# Class 和 Class> 区别
// 通过反射的方式生成 multiLimit// 对象,这里比较明显的是,我们需要使用强制类型转换MultiLimit multiLimit = (MultiLimit)Class.forName("com.glmapper.bridge.boot.generic.MultiLimit").newInstance();
对于上述代码,在运行期,如果反射的类型不是 MultiLimit 类,那么一定会报
java.lang.ClassCastException 错误。

// 可以public Class> clazz;// 不可以,因为 T 需要指定类型public ClassclazzT;

public class Test3{ public Class> clazz;// 不会报错public ClassclazzT;
# 小结
热门推荐:

点分享 点点赞 点在看
评论



