我读过一些关于Java中的CovarianceContravarianceInvariance的文章,但我对它们感到困惑.

我使用的是Java 11,我有一个类层次 struct A => B => C(意味着CBA的子类型,BA的子类型)和一个类Container:

class Container<T> {
    public final T t;
    public Container(T t) {
        this.t = t;
    }
}

例如,如果我定义了一个函数:

public Container<B> method(Container<B> param){
  ...
}

这是我的困惑,为什么第三行要编译?

method(new Container<>(new A())); // ERROR
method(new Container<>(new B())); // OK
method(new Container<>(new C())); // OK Why ?, I make a correction, this compiles OK

如果在Java中,泛型是invariant.

当我定义这样的东西时:

Container<B> conta =  new Container<>(new A()); // ERROR, Its OK!
Container<B> contb =  new Container<>(new B()); // OK, Its OK!
Container<B> contc =  new Container<>(new C()); // Ok, why ? It's not valid, because they are invariant

推荐答案

这个问题的例子没有证明泛型的不变性.

一个确实证明了这一点的例子是:

ArrayList<Object> ao = new ArrayList<String>(); // does not compile

(您可能错误地认为上面的代码是可编译的,因为StringObject的子类.)

这个问题向我们展示了构造Container<B>个对象的不同方法——由于ABC的继承层次 struct ,有些对象可以编译,有些则不能.

菱形运算符<>表示所创建的容器在任何情况下都是B类型.

如果你举下面的例子:

Container<B> contc =  new Container<>(new C()); // compiles

然后用C填充菱形重新编写,你会发现以下内容不可编译:

Container<B> contc =  new Container<C>(new C()); // does not compile

这将给您带来与我的ArrayList个示例相同的"不兼容类型"编译错误.

Java相关问答推荐

Java Swing:初始化身份验证类后未检测到ATM_Interface键事件

Spring Boot@Cachebale批注未按预期工作

Spring Boot 3.2.2中的@Inject和@Resource Remove

将带有js文件的 bootstrap 程序导入maven项目时出错

我不能再在Android Studio Hedgehog上用Java语言创建新项目了吗?

Bean定义不是从Spring ApplationConext.xml文件加载的

如何使用SpringBoot中的可分页对整数作为字符串存储在数据库中时进行排序

内存和硬盘中的Zip不同,这会导致下载后的Zip损坏

Kotlin Val是否提供了与Java最终版相同的可见性保证?

如何在盒子的顶部和底部创建两张不同图片(大小相同)的盒子?

如何使用MapStrCut转换双向链接

嘲笑黄瓜中的对象

在应用getCellFormula()时,Excel引用中的文件名始终为";[1]";使用Apache POI()

为什么mvn编译生命周期阶段不只是编译已更改的java文件?

如何设置默认序列生成器分配大小

始终使用Spring Boot连接mongodb上的测试数据库

转换为JSON字符串时,日期按天递减-Java

[Guice/MissingImplementation]:未绑定任何实现

语句打印在错误的行(Java Token 问题)

Keycloak + Spring Boot 角色认证不起作用