最近被问到了泛型的通配符和类型限定的问题,<T extends 数据类型>
和 <? extentds 数据类型>
有什么区别,以前也经常分不清”T“和”?“的关系,后来看了Java的官方教程《Lesson: Generics》才明白他们的区别主要有两个方面:
-
”T“ 是一个形参,表示所有String类的派生类其中的 ”某一个类”,当使用的时候会被强转成传入的具体类型,而”?“是一个实参,表示所有String类的派生类的集合,可以理解为一个范围。比如:
class Fruit{ public void getName(){ print("Fruit") } } class Apple extends Fruit{ @override public void getName(){ print("Apple") } } class Generic<T extend Fruit>{ T data; public void getFruitName(T t){ t.getName() } public void setData(T t){ data = t; } public T getData(){ return data; } } public void setGeneric(Generic<? extends Fruit> generic){ }
<T extend Fruit>
限定了泛型的上边界为Fruit,所以new Generic<Fruit>
或着new Generic<Apple>
都是可以的,可以通过t.getName()调用Fruit及其派生类的getName方法。而在setGeneric()方法只要传入的Generic类的泛型是Fruit类及其子类就可以,但是无法通过?.getName()方法调用Fruit及其子类的方法。
-
“T”和“?”运用的地方不同,“?”是定义在引用变量上,“T”是类上或方法上。比如:
class Generic<T extends Fruit>{ T data; public void setData(T t){ data = t; } } public <T extends Fruit> void testOne(Generic<T> generic){ generic.show() } public void testTwo(Generic<? extends Fruit> generic){ generic.show() }
-
类型限定只有
<T extends 数据类型>
,只能设定上边界,而通配符既可以设定上边界<? extends 数据类型>
也可以设定下边界<? super 数据类型>
-
<? extends 数据类型>
是一种读安全的约束,<? super 数据类型>
是一种写安全的约束。