首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么编译器不产生错误,因为类型的不变性被违反了。

为什么编译器不产生错误,因为类型的不变性被违反了。
EN

Stack Overflow用户
提问于 2017-09-06 10:53:20
回答 1查看 32关注 0票数 2

一个例子来自布鲁斯·艾克尔的书“解说中的问题”。

代码语言:javascript
复制
class GenericWriting{
static <T> void writeExact(List<T> list, T item) {
    list.add(item);
}
static List<Apple> apples = new ArrayList<Apple>();
static List<Fruit> fruits = new ArrayList<Fruit>();
static void f1() {
    writeExact(apples, new Apple());
    writeExact(fruits, new Apple()); /* why the compiler does not produce an error because the invariance of types is violated */
}
static <T> void writeWithWildcard(List<? super T> list, T item) {
    list.add(item);
}
static void f2() {
    writeWithWildcard(apples, new Apple());
    writeWithWildcard(fruits, new Apple());
}

public static void main(String[] args) {
    f1();
    f2();
}
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-09-06 11:18:48

这是由于多态。

通常,如果您编写这样的方法:

代码语言:javascript
复制
private static void method(Fruit f) {}

你可以用new Apple()来调用它

代码语言:javascript
复制
method(new Apple());

对吗?因为AppleFruit的子类。

当您调用方法时:

代码语言:javascript
复制
writeExact(fruits, new Apple());

由于您没有显式指定T,所以编译器试图推断它。它看到第一个参数fruits是一个List<Fruit>。它认为T一定是Fruit。现在,您的方法如下:

代码语言:javascript
复制
static void writeExact(List<Fruit> list, Fruit item)

看见?将一个苹果传递给第二个参数是完全正确的,因为AppleFruit的一个子类。

另一方面,如果指定泛型T to be应用程序,则会发生以下错误:

代码语言:javascript
复制
List<Fruit> list = new ArrayList<>();
// compiler error!
GenericWriting.<Apple>writeExact(list, new Apple());

因为List<Fruit>List<Apple>不兼容。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46073344

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档