对比extends和super通配符 我们再回顾一下extends通配符。作为方法参数,类型和类型的区别在于:
允许调用读方法T get()获取T的引用,但不允许调用写方法set(T)传入T的引用(传入null除外);
允许调用写方法set(T)传入T的引用,但不允许调用读方法T get()获取T的引用(获取Object除外)。
一个是允许读不允许写,另一个是允许写不允许读。
{collapse-item label="擦处法"}
擦拭法决定了泛型:
不能是基本类型,例如:int; 不能获取带泛型类型的Class,例如:Pair.class; 不能判断带泛型类型的类型,例如:x instanceof Pair; 不能实例化T类型,例如:new T()。 泛型方法要防止重复定义方法,例如:public boolean equals(T obj);
子类可以获取父类的泛型类型。
{/collapse-item} {collapse-item label="extends通配符"}
//extends通配符 允许读不允许写 使用类似通配符作为方法参数时表示: 方法内部可以调用获取Number引用的方法,例如:Number n = obj.getFirst();; 方法内部无法调用传入Number引用的方法(null除外),例如:obj.setFirst(Number n);。 即一句话总结:使用extends通配符表示可以读,不能写。 使用类似定义泛型类时表示: 泛型类型限定为Number以及Number的子类。
Pair p1=new Pair<>(12.3,4.56);
int n=setsa(p2);//读取
System.out.println(n);
//extends通配符 允许读不允许写
static int setsa(Pair p){
Number fi=p.getFirst();
Number la=p.getLast();
return p.getFirst().intValue()+p.getFirst().intValue();
}
class Pair {
private T first;
private T last;
public Pair(T first, T last) {
this.first = first;
this.last = last;}
public T getFirst() {return first;}
public T getLast() {return last;}
public void setFirst(T first) {this.first = first;}
public void setLast(T last) {this.last = last;}
}
{/collapse-item}
{collapse-item label="super通配符"}
使用通配符表示: 允许调用set(? super Integer)方法传入Integer的引用; 不允许调用get()方法获得Integer的引用。 唯一例外是可以获取Object的引用:Object o = p.getFirst()。 换句话说,使用通配符作为方法参数,表示方法内部代码对于参数只能写,不能读。
//super通配符
// 注意到Pair表示,
//Pair是所有Pair的超类
// 方法参数接受所有泛型类型为Integer或Integer父类的Pair类型。
Pair p1=new Pair<>(12.3,4.56);
Pair p2=new Pair<>(123,456);
setSame(p1,456);
setSame(p2,123);//写入
Pairp3=p1;//安全地向上转型
System.out.println(p3.getFirst()+","+p3.getLast());
System.out.println(p1.getFirst()+" "+p1.getLast());
System.out.println(p2.getFirst()+" "+p2.getLast());
//super通配符 允许写不允许读。
static void setSame(Pair p, Integer n) {
p.setFirst(n);
p.setLast(n);
}
class Pair {
private T first;
private T last;
public Pair(T first, T last) {
this.first = first;
this.last = last;}
public T getFirst() {return first;}
public T getLast() {return last;}
public void setFirst(T first) {this.first = first;}
public void setLast(T last) {this.last = last;}
}
{/collapse-item}
{collapse-item label="super跟extends运用"}
copy()方法的定义就完美地展示了extends和super的意图:
copy()方法内部不会读取dest,因为不能调用dest.get()来获取T的引用;
copy()方法内部也不会修改src,因为不能调用src.add(T)。
// 把src的每个元素复制到dest中:
public static void copy(List dest, List src) {
for (int i=0; i
{/collapse-item}
{collapse-item label="其他"}
{message type="info" content="
//Pair是所有Pair的超类
void sample(Pair p) {
}
因为通配符既没有extends,也没有super,因此:
不允许调用set(T)方法并传入引用(null除外);
不允许调用T get()方法并获取T引用(只能获取Object引用)。
换句话说,既不能读,也不能写,那只能做一些null判断:"/}
{/collapse-item}
本文共 742 个字数,平均阅读时长 ≈ 2分钟