我对泛型中extends和super关键字的理解

《Java编程思想》泛型

之前在读《Java编程思想》中的泛型一章时,对于? super MyClass为什么叫超类型通配符一直不理解,既然可以往List中添加Apple的子类,那?代表的不应该是子元素吗,如果代表的是子元素,那? extends MyClass? super MyClass有啥区别啊。今天终于从牛角尖里钻出来了,感觉自己之前好蠢,理解能力太差,哈哈哈哈...

public class GenericTest {

    public static void main(String[] args) {
        List list1 = new ArrayList();
        List list2 = new ArrayList();        
        // 这样会报错,因为?代表的是Apple的父类
        List list3 = new ArrayList();

        list2.add(new RedApple());
        // 这样会报错,因为list2中的元素为Apple
        list2.add(new Fruit());

        Object obj = list1.get(0);
        // 这样会报错
        Fruit fruit = list1.get(0);
        // 这样也会报错
        Apple apple = list1.get(0);
        // 这样还会报错
        RedApple redApple = list1.get(0);
    }

    private static class Fruit {}

    private static class Apple extends Fruit {}

    private static class RedApple extends Apple {}
}

其实List的含义是指现有的这个容器中的元素要么是Apple,要么是Apple的父类。可以看到给List赋值为ArrayList()ArrayList()是没问题的,但是赋值为ArrayList()就会报错,因为RedAppleApple的子类,不符合List的声明。这样称super超类型通配符也就说的通了,而且Apple位于继承树的最底下,所以也可以称super下界通配符
既然List中的元素是AppleApple的父类,那么向List中添加RedApple也是合法的,因为RedApple也是Apple啊,但是添加Fruit是不行的,因为List中存放的元素可能为Apple。当从List中获取元素时,只能获取到Object类型,因为假如Apple为接口类型的话,那么元素的父类就不确定了,但所有的类都继承自ObjectObject是确定的。所以父类型通配符一般用于向一个泛型类型中“写入”(传递给一个方法)。

public class GenericTest {

    public static void main(String[] args) {
        List list1 = new ArrayList();
        List list2 = new ArrayList();
        // 这样会报错,因为?代表的是Fruit的子类
        List list3 = new ArrayList();
        
        // 这里0索引是没有值的哈,主要是说明下extends的特性
        Fruit fruit = list2.get(0);

        // 这样会报错
        list2.add(new Orange());
    }

    private static class Plant {}

    private static class Fruit extends Plant {}

    private static class Apple extends Fruit {}

    private static class Orange extends Fruit {}

}

super相反,List的含义是指现有的这个容器中的元素要么是Fruit,要么是Fruit的子类,所以称extends子类型通配符,因为容器中的所有元素都继承自Fruit,所以Fruit是所有元素的上界,也就可以称extends上界通配符
既然List中的元素都是Fruit的子类,那么从List中获取类型为Fruit的元素自然也是合法的。但是向List中添加元素是不允许的,可以看到虽然list2的引用类型为List,看上去好像可以向其中添加Orange对象,但list2实际上是ArrayList类型的列表,里面的元素都是Apple,而OrangeApple是没有关系的。所以子类型通配符一般用于从一个泛型类型中“读取”(从一个方法中返回)。

你可能感兴趣的:(我对泛型中extends和super关键字的理解)