聊一聊Java 泛型通配符 T,E,K,V,?
好好学java
共 2315字,需浏览 5分钟
·
2021-10-27 09:42
今日推荐
论异步编程的正确姿势:十个接口的活现在只需要一个接口就能搞定!
让SpringBoot不再需要Controller、Service、Mapper,这款开源工具绝了!
| 前言
public class GlmapperGeneric<T> {
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 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 才能使用
private E test(K arg1, E arg2){
E result = arg2;
arg2.compareTo(arg1);
//.....
return result;
}
类型参数列表中如果有多个类型参数上限,用逗号分开
下界通配符 < ? super E>
下界: 用 super 进行声明,表示参数化的类型可能是所指定的类型,或者是此类型的父类型,直至 Object
private void 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 来 确保 泛型参数的一致性
publicvoid
test(Listdest, List src)
//通配符是 不确定的,所以这个方法不能保证两个 List 具有相同的元素类型
public void
test(List extends Number> dest, List extends Number> src)
GlmapperGeneric glmapperGeneric = new GlmapperGeneric<>();
Listdest = new ArrayList<>();
Listsrc = new ArrayList<>();
glmapperGeneric.testNon(dest,src);
区别2:类型参数可以多重限定而通配符不行
区别3:通配符可以使用超类限定而类型参数不行
T extends A
? extends A
? super A
| Class
和 Class>
区别
Class
和
又有什么区别呢?Class
和 Class>
// 通过反射的方式生成 multiLimit
// 对象,这里比较明显的是,我们需要使用强制类型转换
MultiLimit multiLimit = (MultiLimit)
Class.forName("com.glmapper.bridge.boot.generic.MultiLimit").newInstance();
Class
在实例化的时候,T 要替换成具体类。Class>
它是个通配泛型,? 可以代表任何类型,所以主要用于声明时的限制情况。比如,我们可以这样做申明:// 可以
public Class> clazz;
// 不可以,因为 T 需要指定类型
public ClassclazzT;
public Class clazzT;
这样的话,就必须让当前的类也指定 T ,public class Test3<T> {
public Class> clazz;
// 不会报错
public ClassclazzT;
| 小结
推荐文章
1、一款高颜值的 SpringBoot+JPA 博客项目 2、超优 Vue+Element+Spring 中后端解决方案 3、推荐几个支付项目! 4、推荐一个 Java 企业信息化系统 5、一款基于 Spring Boot 的现代化社区(论坛/问答/社交网络/博客)
评论