再论<? extends T>和<? super T>

参考:

https://www.cnblogs.com/drizzlewithwind/p/6100164.html

Java 泛型 <? super T> 中 super 怎么 理解?与 extends 有何不同? - 胖君的回答 - 知乎
https://www.zhihu.com/question/20400700/answer/117464182

说得很清楚,但是有一处没说明白(知乎上有人提出来了):

使用<? super Fruit>时,子类类型也接受:

		Plate<? super Fruit> p2 = new Plate<>(new Fruit());
		p2 = new Plate<>(new Food());
		p2 = new Plate<>(new Fruit());
		p2 = new Plate<>(new Apple()); // 这是个子类型

新写一版,不引入Plate类,直接用JAVA自己的ArrayList类来做测试。

public interface List<E> extends Collection<E> {
    ...
    boolean add(E e);
    ...
    E get(int index);
    ....
}
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable{...}

定义三个类,Fruit->Apple->RedApple,声明ArrayList,有如下现象:

import java.util.*;
public class 泛型_通配符边界2 {
	public static void main(String[] args) {
		ArrayList<Apple> p1 = new ArrayList<Apple>();
		// 【震惊!装得了苹果,装不了红苹果】
		// ↓Type mismatch:
		// cannot convert from ArrayList<RedApple> to ArrayList<Apple>
		// ArrayList<Apple> p2 = new ArrayList<RedApple>();
	}
}
class Fruit {
}
class Apple extends Fruit {
}
class RedApple extends Apple {
}

解决方案就是

【1.<? extends Fruit>,定类型继承关系的上界】
【2.<? super Apple>,确定类型继承关系的下界】

解决方案如下,照着注释看便是

package ah;
import java.util.*;
public class 泛型_通配符边界2 {
	public static void main(String[] args) {
		ArrayList<Apple> p1 = new ArrayList<Apple>();
		// 【震惊!装得了苹果,装不了红苹果】
		// ↓Type mismatch:
		// cannot convert from ArrayList<RedApple> to ArrayList<Apple>
		// ArrayList<Apple> p2 = new ArrayList<RedApple>();
		// 【1.<? extends Fruit>,定类型继承关系的上界:】
		// 能装Apple以及一切Apple的派生类
		ArrayList<? extends Apple> p3 = new ArrayList<Apple>();
		p3 = new ArrayList<RedApple>();
		// ↓上层的类不接受
		// Type mismatch:
		// cannot convert from ArrayList<Fruit> to ArrayList<? extends Apple>
		// p3 = new ArrayList<Fruit>();
		// 【然而,extends是只读的,不能写入】
		// p3.add(new Apple());
		if (p3.size() != 0) {
			Apple apple = p3.get(0);
		}
		// 【2.<? super Apple>,确定类型继承关系的下界】
		// 能装苹果以及一切苹果的基类
		ArrayList<? super Apple> p4 = new ArrayList<Apple>();
		p4 = new ArrayList<Fruit>();
		p4 = new ArrayList<Apple>();
		// Type mismatch:
		// cannot convert from ArrayList<RedApple> to ArrayList<? super Apple>
		// p4 = new ArrayList<RedApple>();
		// 【可读可写,读出来的是Object类型】
		p4.add(new RedApple());// 子类对象但是可以写进入,因为默认向上转型
		Object object = p4.get(0);
		System.out.println(object);
		// 最后,JDK 7之后,ArrayList后面的<>里什么都不用写
		List<Apple> p2 = new ArrayList<>();
	}
}
class Fruit {
}
class Apple extends Fruit {
}
class RedApple extends Apple {
}
posted @ 2019-04-05 19:06  虎老狮  阅读(404)  评论(0编辑  收藏  举报