前言

Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许开发者在编译时检测到非法的类型。

泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

泛型带来的好处

在没有泛型的情况的下,通过对类型 Object 的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是本身就是一个安全隐患。

那么泛型的好处就是在编译的时候能够检查类型安全,并且所有的强制转换都是自动和隐式的。

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(){
????????GlmapperGeneric<String>?glmapperGeneric?=?new?GlmapperGeneric();
????????glmapperGeneric.set("test");
????????//?不需要强制类型转换
????????String?test?=?glmapperGeneric.get();
????????System.out.println(test);
????}
}

上面这段代码中的 specifyType 方法中 省去了强制转换,可以在编译时候检查类型安全,可以用在类,方法,接口上。

泛型中通配符

我们在定义泛型类,泛型方法,泛型接口的时候经常会碰见很多不同的通配符,比如 T,E,K,V 等等,这些通配符又都是什么意思呢?

常用的 T,E,K,V,?

本质上这些个都是通配符,没啥区别,只不过是编码时的一种约定俗成的东西。比如上述代码中的 T ,我们可以换成 A-Z 之间的任何一个 字母都可以,并不会影响程序的正常运行,但是如果换成其他的字母代替 T ,在可读性上可能会弱一些。通常情况下,T,E,K,V,?是这样约定的:

  • ?表示不确定的 java 类型
  • T (type) 表示具体的一个java类型
  • K V (key value) 分别代表java键值中的Key Value
  • E (element) 代表Element

?***通配符

我有一个父类 Animal 和几个子类,如狗、猫等,现在我需要一个动物的列表,我的第一个想法是像这样的:

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)?{
????List<Dog>?dogs?=?new?ArrayList<>();
????//?不会报错
????countLegs(?dogs?);
????//?报错
????countLegs1(dogs);
}

当调用 countLegs1 时,就会飘红,提示的错误信息如下:

那如果也想?public Class<T> clazzT;?这样的话,就必须让当前的类也指定 T ,

public?class?Test3<T>?{
????public?Class<?>?clazz;
????//?不会报错
????public?Class<T>?clazzT;

菲律宾太阳娱乐网址现金网网上娱乐场:最后

感谢大家看到这里,文章有不足,欢迎大家指出;如果你觉得写得不错,那就给我一个赞吧。

也欢迎大家关注我的公众号:程序员麦冬,每天更新行业资讯!