泛型的概念
在没有泛型的出现之前,一般的类和方法中,只能使用具体的类型,要么是基本的类型,要么就是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。
泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许开发者在编译时检测到非法的类型。在Thinking in Java中,对泛型的术语解释是:“适用于很多很多的类型”,它最初出现是希望类和方法能具备最广泛的表达能力。
泛型的本质是参数化类型,也就是说所将参数指定为一个数据类型。
泛型的优势
在没有泛型之前,通常用Object来实现参数的任意化,例如我们可以使用ArrayList集合来存储各种对象,但是如果不使用泛型,我们在取这个集合中的数据的时候就需要手动强制转换集合中的元素,这样就要求我们开发的时候必须清楚的知道集合中的数据类型,即使我们知道了集合中的数据类型,并且将它强制转换,但也存在一定的安全隐患,因为在强制转换之后,编译器就不会报错,这样如果集合中的数据类型和我们强制转换的类型不一样,这个错误我们无法在编译时期得知,只有在运行程序的字节码文件的时候才能得到**java.lang.ClassCastException:**这个错误。
而但我们使用泛型的时候,就会默认使用隐式转换,并且将错误在编译时期就暴露出来,这样就提高了程序的安全性
泛型中常用的通配符
通配符 | 作用 |
---|---|
T | 具体的一个java类型 |
E | Element |
K,V | 代表java键值中的Key Value |
? | 不确定的 java 类型 |
上界通配符 < ? extends E>
含义:传入的参数类型需为E或E的字类对象,这样做有两个方便的地方,一是如果传入的类型不是 E 或者 E 的子类,编译不成功,二是,泛型中可以使用 E 的方法,要不然还得强转成 E 才能使用
下界通配符< ? super E>
含义:传入的参数需为E或E的父类,这个父类也可以是Object。
?和T的区别?
T 是一个 确定的 类型,通常用于泛型类和泛型方法的定义,?是一个 不确定 的类型,通常用于泛型方法的调用代码和形参,不能用于定义类和泛型方法。
区别1:通过 T 来 确保 泛型参数的一致性
// 通过 T 来 确保 泛型参数的一致性
public <T extends Number> void
test(List<T> dest, List<T> src)
//通配符是 不确定的,所以这个方法不能保证两个 List 具有相同的元素类型
public void
test(List<? extends Number> dest, List<? extends Number> src)
区别2:类型参数可以多重限定而通配符不行
使用 & 符号设定多重边界(Multi Bounds),指定泛型类型 T 必须是 MultiLimitInterfaceA 和 MultiLimitInterfaceB 的共有子类型,此时变量 t 就具有了所有限定的方法和属性。对于通配符来说,因为它不是一个确定的类型,所以不能进行多重限定。
区别3:通配符可以使用超类限定而类型参数不行
类型参数 T 只具有 一种 类型限定方式:
T extends A
但是通配符 ? 可以进行 两种限定:
? extends A
? super A
以上部分摘抄自:https://juejin.im/post/6844903917835419661