@[toc]
概述
泛型是 java 中非常重要的概念,在面向对象编程和设计模式中有非常广泛的运用
泛型即参数化类型,操作的数据被指定为一个参数,可以用在类,接口和方法中,分别称为类泛型,接口泛型,方法泛型
泛型只在 java 编译阶段起作用,编译之后程序去泛型化,泛型不会进入到程序的运行阶段
T 可以随便写为任意标识,常见的如 T、E、K、V 等形式的参数常用于表示泛型,但是传入的只能是类类型,不能是简单类型
泛型类 class Demo
类通过加上泛型,可以完成对一组类的操作和对外开放相同的接口,非常的典型比如 List,Map,Set 等
举例说明:
public class Demo<T> {
// 这个 T 由类实例化的时候的 <T> 指定的
private T key;
// 这个 T 也是由类实例化的时候 <T> 指定的
public void setKey(T key) {
this.key = key;
}
// 返回类型 T 也是由类实例化时候指定的
public T getKey() {
return this.key;
}
}
一旦我们定义了List<String> list就表示了该 list 中各个方法在编译阶段就被识别 T 表示 String 了,所以只能承接 String 类型,如果添加了 Integer 类型,运行就会报错
泛型接口 interface Demo
与泛型类很相似,距离说明:
public interface Demo<T> {
public T next();
}
泛型方法
方法的返回值前加<T>表示此方法是泛型方法
举例说明:
public <T> T getMapper(Class<T> type) {
// todo...
}
第一个<T>表示该方法是一个泛型方法
第二个 T 表示这个方法的返回类型
第三个Class<T>表示获取 T 类型的 Class
再看一个例子就会明白泛型中的 T 的传递
public <T,K> K showKeyName(Generic<T> container){
// todo:
}
其他
泛型通配符 <?>
为什么会用到泛型通配符呢,啥又是泛型通配符呢,这里做个举例:
public void function(List<String> list) {
// todo:
}
List<String> list1 = new List<>();
List<Integer> list2 = new List<>();
function(list1);
function(list2);
最后运行,function(list1)没有啥问题,但是function(list2)会有问题,所以我们该怎么调整呢,可以使用泛型通配符来解决这个问题,如下所示即可解决问题:
public void function(List<?> list) {
// todo:
}
List<String> list1 = new List<>();
List<Integer> list2 = new List<>();
function(list1);
function(list2);
这样最后两个 function 都能正常运行了,List<?> 的 ? 表示未知类型
泛型类中的泛型方法
举个例子说明一下:
public class Demo<T> {
public void function1(T t) {
// todo:
}
public <E> function2(E e) {
// todo:
}
}
这里的泛型方法 function2 前的 E 不是来源于泛型类的 T,一旦泛型类前标明了<E>就表示该方法是一个泛型方法,其泛型类型不是来自于类泛型,而是新的泛型类型,所以这个泛型类的泛型方法的形参类型不是来自实例化类所带过来的泛型,而是来自于其泛型方法自身的泛型,而 function1 形参中的 T 才是来自于实例化所带来的泛型