Java泛型的理解与使用

「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

Java泛型是在JDK5开始引入的一个新特性,可以用来检测非法的类型。

一 常见的通配符

泛型中常用的通配符,实际上采用任意字母都可以,通常情况下,都会采用常见的几个通配符(T,E,K,V,?)。以下是他们大致的意义:

  • ?表示不确定的java类型
  • T表示具体的一个java的类型
  • K和V代表java的key和value键值对
  • E代表Element

1 T等通配符

泛型变量T等只能用在类,接口以及函数中声明后才能使用。

2 如何使用?无界通配符

?是一个无界的通配符,可以代表任意的类

实际上的用法参考以下代码:

ClassA<?> class;
复制代码

这时候,不管是传什么类型的类都能实现,例如:

class = new ClassA<Integer>(1,2,3,4);
复制代码

也可以字符串的;

class = new ClassA<String>("","","");
复制代码

注意:?是不允许 new Class<?>()这样使用。

Class<?>和Class的区别:

Class 需要转换为具体的类,但是Class<?>通赔的泛型,可以代表任何类型。

上届通配符<? extends E>

这里的extends不代表继承,整个的意思是:指定的类型为E类型的子类。

好处:如果传入的类型不是E的类型,就会报错,避免强转换。

?表示任意的类,而这里的E表示一个父类。指定了属于父类E的子类才可以使用。

一种情况例子:

public void test(List<? extends Number> number){}
复制代码

这里表示传入到此方法的list数组,必须是父类为Number的数组才能够作为对象传入。

如果传入的list不是Number的子类,那么就会报错。

另一种情况是:

public <K extends ClassA,V extends ClassB> K test(K k, V v){}
复制代码

这种的方法的描述信息是:<K extends ClassA,V extends ClassB>的意思:k必须为ClassA的子类,V必须为ClassB的子类,此方法的返回值为K类型,传入的参数为K类型和V类型的参数。

注意:ClassA中的参数和方法K都可以使用,V也是同理。只可以取K中的值,但是不能做修改。

但是呢,如果要绑定多个类型怎么办?

一般可以使用&来进行绑定,例如下面例子:

public static <T extends ClassA & ClassB,E extends ClassC> T test(T t, E e){}
复制代码

这里表示的是,T类型要同时满足是A类和B类的子类(必须是共有的),E为C类的子类,返回类型为T。

如果一个类中使用了:

public class Point<T extends Number>{}
复制代码

表示的是,该类的被T定义的变量是无法被修改的,只能获取。

为何不能赋值:因为指定的类型是未知的,不允许将未知类型的值传到类内部中。

下界通配符<? super E>

?表示的是泛型的参数必须是E或者E的父类。

例如代码

class CEO extends Manager {  }    class Manager extends Employee {  }    class Employee {  }  
复制代码

在实现的时候

List<? super Manager> list;
list = new ArraryList<Employee>();  //可行
list = new ArraryList<Manager>();    //可行
list = new ArraryList<CEO>();        //不可行
复制代码

在存值的时候,Manager和CEO都可以存,但是Employee不确定类型,无法存储。只能确定前两个。