<? extends ...>与<? super ...>区别与理解
一、<? extends …>extends指上界通配符,示例中指的是所有Fruit类及其派生的子类。对该通配符指示的容器进行写入操作(set),就像收到一个包裹,上面写了包裹里都是水果,但编译器并不事先知道具体是哪一种水果,如果里面是香蕉,但放入了一个苹果就会造成错误,所以编译器禁止这种操作。public void Func( List <? extends Fruit>
一、<? extends …>
extends指上界通配符,示例中指的是所有Fruit类及其派生的子类。
对该通配符指示的容器进行写入操作(set),就像收到一个包裹,上面写了包裹里都是水果,但编译器并不事先知道具体是哪一种水果,如果里面是香蕉,但放入了一个苹果就会造成错误,所以编译器禁止这种操作。
public void Func( List <? extends Fruit> temp)
{
temp.set(...); //compile time error
}
而对该通配符指示的容器进行读取操作(get),就像从包裹里拿一个水果,传递给一个Fruit对象。编译器无需关心到底是什么水果,因为Fruit类一定是该水果的超类,用Fruit对象调用的方法一定是该水果定义了的,不会发生错误。
二、super
super指下界通配符,示例中指的是所有Fruit类及其超类。
对该通配符容器进行读取(get)操作,就像收到一个包裹,里面是水果或者食物,但编译器不知道到底是什么,如果拿出一个并传递给一个Fruit对象,就有可能发生"超类对象被子类引用调用一个不存在的方法",造成错误。
public void Func( List <? super Fruit> temp)
{
Fruit a = temp.get(); //compile time error .
//if not so,assume return an Food obj, refered by a Fruit variable,it seems to be ok
//a.Fruitcolor(); // Food obj don't have a method defined in Fruit class, oop!
}
而对其进行写入(set)操作,就像向包裹中放入东西,只要保证放入的东西是Fruit的子类,编译器无需直到容器具体的类型,就可以保证容器不会“调用一个不存在的方法”
三、总结
总结起来,编译器检查,如果可以确保总是用超类变量引用其子类对象,那么之后通过该变量调用的方法,一定在子类中已被定义。
而一旦出现用子类变量引用超类对象的情况,尽管其后也许并不一定发生错误,但编译器无法确定这一点,只能触发编译错误。
摘自:
作者:BJChangAn
链接:https://www.jianshu.com/p/447e13647824
来源:简书
更多推荐
所有评论(0)