关于泛型类型通配符的小知识点

  • 对于类型通配符
import java.util.ArrayList;
import java.util.List;

class Fruit{}
class Apple extends Fruit{}
class Orange extends Fruit{}

public class Main {
  public static void main(String[] args) {
    List<? extends Fruit> fruits;
    List<Apple> apples = new ArrayList<>();
    List<Orange> oranges = new ArrayList<>();
    apples.add(new Apple());

    oranges.add(new Apple());       //编译错误
    fruits = oranges;

      /*这和上一个注释掉的语句作用相同,因此这里List<? extends Fruit> fruits不能添加Apple对象*/
    fruits.add(new Apple());          //编译错误
      
      /*这和上上一个注释掉的语句作用相同,因此这里List<? extends Fruit> fruits甚至不能添加Object对象*/
    fruits.add((Object)new Apple());      //编译错误
      
      /*任何参数里涉及泛型的函数由于安全问题都无法正常使用,get方法没有泛型,返回时Object,因此可以正常使用*/
    fruits.get(1);      
  }
}

对于`List<? extends Fruit> fruits,应当将其解读为

具有任何从Fruit继承的类型的列表

而不应该是

这个List将持有任何类型的Fruit

  • 对于超类型通配符
import java.util.ArrayList;
import java.util.List;

class Fruit{}
class Apple extends Fruit{}
class Orange extends Fruit{}
class Jonathan extends Apple{}

public class Main2 {

  public static void main(String[] args) {
    
    List<? super Apple> fruits;
    List<Apple> apples = new ArrayList<Apple>();
    fruits = apples;
    
    /*fruits 的基类是Apple,因此可以添加任何Apple类型及其子类,无法添加Object */
    fruits.add(new Apple());
    fruits.add(new Jonathan());
    list1.add(new Object());    //编译错误
    
    /*get函数正常,原理相同*/
    fruits.get(1);
  }
}


  • 总结

    出于类型安全考虑

    • 对于List<? extends Apple> apple,不能使用add()方法添加任何对象
    • 对于List<? super Apple> apples,可以使用add()方法添加Apple对象及其子类对象

参考资料:Java编程思想 P390-P393

如有错误还请指正

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容