zoukankan      html  css  js  c++  java
  • 再论<? 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 {
    }
    
  • 相关阅读:
    android 入门-工程属性介绍
    android 入门-android属性介绍
    android 入门-布局
    android 入门-动画与容器
    android 入门- 词汇
    android 入门-引用库项目
    android 入门-防微信拍摄视频 按钮事件处理
    WPF Adorner
    c# Quartz.net的简单封装
    WPF 触摸屏小键盘样式
  • 原文地址:https://www.cnblogs.com/tigerlion/p/10659515.html
Copyright © 2011-2022 走看看