gpt4 book ai didi

java - 为什么边界在 Java 中如此奇怪?

转载 作者:搜寻专家 更新时间:2023-11-01 02:38:31 27 4
gpt4 key购买 nike

我正在使用 Java 8。在通过 Java OCP 8 的培训期间,我发现了一些我不理解但想知道的代码片段,为什么对我来说如此奇怪。

我有下一个层次结构:

class A {}
class B extends A {}
class C extends B {}

第一个,这段代码是可行的:

List<?> list1 = new ArrayList<A>() { 
{
add(new A());
}
};

但是接下来的代码不起作用,编译错误:

list1.add(new A());

那么,为什么我们不能通过这种方式添加新记录呢?

第二个,这段代码是有效的:

List<? extends A> list2 = new ArrayList<A>() {
{
add(new A());
add(new B());
add(new C());
}
};

但是接下来的代码不起作用,编译错误:

list2.add(new A());
list2.add(new B());
list2.add(new C());

最后一个,这段代码是有效的:

List<? super B> list3 = new ArrayList<A>() {
{
add(new A());
add(new B());
add(new C());
}
};

但是在接下来的代码中,当我们添加new A()时,编译错误:

list3.add(new A()); // compilation error
list3.add(new B());
list3.add(new C());

感谢您的回答!

最佳答案

这是一个旨在强制类型安全的编译错误。如果编译器允许您这样做,想象一下会发生什么:

对于问题 1,一旦对象 list1已经声明,编译器只考虑声明的类型,即List<?>并忽略了它最近分配给 ArrayList<A> 的事实.

List<?> list1 = ...;  // The compiler knows list1 is a list of a certain type
// but it's not specified what the type is. It could be
// a List<String> or List<Integer> or List<Anything>
list1.add(new A()); // What if list1 was e.g. a List<String>?

但是:

List<?> list1 = new ArrayList<A>() { 
{
add(new A());
}
};

在这里,您要分配给 list1一种表达。表达式本身,即 = 之后的所有内容, 不使用 ? , 实际上是一个扩展了 ArrayList<A> 的匿名类并有一个调用 add(new A()) 的初始化程序 block 没关系。

第二个问题(与 list2)具有相同的原因。

第三期,

List<? super B> list3 = new ArrayList<A>() {
{
add(new A());
add(new B());
add(new C());
}
};

list3.add(new A()); // compilation error

编译器看到list3作为List<? super B> .这意味着通用参数可以是 B或其父类(super class),A .如果它是 List<B> 怎么办? ?您不能添加 AList<B> ;因此编译器拒绝此代码。

关于java - 为什么边界在 Java 中如此奇怪?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40176475/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com