extends T> 和 super T> 是Java泛型中的"通配符" 和 “边界(Bounds)”的概念
extends T> 是指 “上界通配符
1.为什么要去使用通配符或者边界的概念
使用泛型的过程中比如 我们有Fruit类,和它的派生类Apple类。
public class Fruit {
private String name;
public Fruit(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Apple extends Fruit {
private boolean isRed;
public Apple(boolean isRed,String name) {
super(name);
this.isRed = isRed;
}
public boolean isRed() {
return isRed;
}
public void setRed(boolean red) {
isRed = red;
}
}
然后有一个最简单的容器:Plate类。盘子里可以放一个东西。我们可以对这个东西做最简单的“放”和“取”的动作:set()和get()方法。
public class Plate<T> {
private T item;
public Plate(T t) {
this.item = t;
}
public T get() {
return item;
}
public void set(T item) {
this.item = item;
}
public static void main(String[] args) {
Plate<Apple> pa=new Plate<Apple>(new Apple(true,"苹果"));
Plate<Fruit> pf = new Plate<Apple>(new Apple(true,"苹果"));
}
}
你会发现第一行内代码编译成功,而第二行代码直接报错了“不兼容的类型,需要Plate
所以为了让泛型用起来更舒服,采用 extends T>,来让泛型之间存在关系。
以下代码表明引用能接受。装水果的盘子或者装苹果,或者装其他水果子类的盘子的引用
Plate<? extends Fruit> pf = new Plate<Apple>(new Apple(true,"苹果"));
先看看往外取取得的是什么类型的对象
public static void main(String[] args) {
Plate<? extends Fruit> pf = new Plate<Apple>(new Apple(true,"苹果"));
Fruit f = pf.get();
Apple a = pf.get();//报错类型不匹配
System.out.println(f.getName());
}
以上代码将pf内的对象取出给Fruit对象并不会出问题,但是在赋值给Apple时报错了,说类型不匹配,Fruit类型不能赋给Apple类型。但是由于我们明确知道存入的是个Apple类型所以可以进行强制类型转换不会出问题
public static void main(String[] args) {
Plate<? extends Fruit> pf = new Plate<Apple>(new Apple(true,"苹果"));
Fruit f = pf.get();
Apple a = (Apple) pf.get();
System.out.println(f.getName());
System.out.println(a.isRed()+a.getName());
}
再看看不能往里存
public static void main(String[] args) {
Plate<? extends Fruit> pf = new Plate<Apple>(new Apple(true,"苹果"));
pf.set(new Apple(true,"苹果"));
pf.set(new Fruit("苹果"));
}
以上代码不管是往盘子里放入水果还是苹果都报错。
原因是编译器只知道容器内是Fruit或者它的派生类,但具体是什么类型不知道。可能是Fruit?可能是Apple?也可能是Banana。所以编译器并不知容器内装了什么,而是标上一个占位符:xxx,表示拥有一个Fruit或Fruit的子类,具体是什么类不知道。然后无论是想往里插入Apple或者Friut编译器都不知道插入的东西的类型能不能和这个已经存放进来的东西(xxx)匹配,容器已经变成了不知道自己能存入什么东西的容器了,所以就都不允许。