使用有界通配符实例化泛型类为何编译失败?与示例代码差异在哪?
Java泛型编译失败原因与差异分析
编译失败的核心原因
- 你声明的
MyArrayList<? extends Shape>使用了上界通配符,它表示这个集合的实际类型参数是Shape的某个子类(包括Shape本身),但编译器无法确定具体是哪一个子类。 - 当调用
add方法时,方法要求接收的参数类型是集合的实际类型参数T,但由于T是未知的,编译器无法验证你传入的Circle或Rectangle是否与这个未知的T匹配——比如history实际可能是MyArrayList<Circle>,此时传入Rectangle会导致类型不兼容,因此编译器直接禁止所有add操作(仅允许传入null)。
与原教程代码的差异
原教程中Gilad Bracha的代码应该是利用? extends Shape进行读取操作(比如调用get方法获取元素并向上转型为Shape),而非写入操作。extends通配符属于生产者通配符,设计目的是安全读取元素,而非写入——这对应泛型中的PECS原则:生产者用extends,消费者用super。
如果需要往集合中添加Shape及其子类对象,可修改声明为以下两种方式之一:
// 方式1:明确使用Shape作为类型参数,直接支持所有Shape子类的存储 private static MyArrayList<Shape> history = new MyArrayList<>(); // 方式2:使用下界通配符,允许存储Shape及其子类 private static MyArrayList<? super Shape> history = new MyArrayList<>();
内容的提问来源于stack exchange,提问作者Evan Aad
相关产品推荐
相关产品推荐

