gpt4 book ai didi

Java Generics Puzzler,扩展类并使用通配符

转载 作者:IT老高 更新时间:2023-10-28 20:30:30 25 4
gpt4 key购买 nike

我一直在反对这个问题一段时间,并认为也许一些新的眼睛会看到这个问题;感谢您的宝贵时间。

import java.util.*;

class Tbin<T> extends ArrayList<T> {}
class TbinList<T> extends ArrayList<Tbin<T>> {}

class Base {}
class Derived extends Base {}

public class Test {
public static void main(String[] args) {
ArrayList<Tbin<? extends Base>> test = new ArrayList<>();
test.add(new Tbin<Derived>());

TbinList<? extends Base> test2 = new TbinList<>();
test2.add(new Tbin<Derived>());
}
}

使用 Java 8。在我看来,它就像在 test 中直接创建容器相当于test2中的容器,但编译器说:

Test.java:15: error: no suitable method found for add(Tbin<Derived>)
test2.add(new Tbin<Derived>());
^

如何写TbinTbinList所以最后一行可以接受吗?

请注意,我实际上将添加键入的 Tbin这就是我指定 Tbin<Derived> 的原因在最后一行。

最佳答案

发生这种情况是因为 capture conversion 的方式作品:

There exists a capture conversion from a parameterized type G<T<sub>1</sub>,...,T<sub>n</sub>> to a parameterized type G<S<sub>1</sub>,...,S<sub>n</sub>>, where, for 1 ≤ i ≤ n :

  • If T<sub>i</sub> is a wildcard type argument of the form ? extends B<sub>i</sub>, then S<sub>i</sub> is a fresh type variable [...].

Capture conversion is not applied recursively.

注意结束位。所以,这意味着,给定这样的类型:

    Map<?, List<?>>
// │ │ └ no capture (not applied recursively)
// │ └ T<sub>2</sub> is not a wildcard
// └ T<sub>1</sub> is a wildcard

仅捕获“外部”通配符。 Map关键通配符被捕获,但 List元素通配符不是。这就是为什么,例如,我们可以添加到 List<List<?>> ,但不是 List<?> .通配符的位置很重要。

将此转移到 TbinList , 如果我们有 ArrayList<Tbin<?>> ,通配符在一个不会被捕获的地方,但是如果我们有一个 TbinList<?> ,通配符在它被捕获的地方。

正如我在评论中提到的,一个非常有趣的测试是这样的:

ArrayList<Tbin<? extends Base>> test3 = new TbinList<>();

我们得到这个错误:

error: incompatible types: cannot infer type arguments for TbinList<>
ArrayList<Tbin<? extends Base>> test3 = new TbinList<>();
^
reason: <strong>no instance(s) of type variable(s) T exist so that
TbinList<T> conforms to ArrayList<Tbin<? extends Base>></strong>

所以没有办法让它按原样工作。需要更改其中一个类声明。


另外,这样想吧。

假设我们有:

class Derived1 extends Base {}
class Derived2 extends Base {}

而且由于通配符允许子类型化,我们可以这样做:

TbinList<? extends Base> test4 = new TbinList<Derived1>();

我们是否可以添加 Tbin<Derived2>test4 ?不,这将是堆污染。我们最终可能会得到 Derived2 s 漂浮在 TbinList<Derived1> .

关于Java Generics Puzzler,扩展类并使用通配符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30384955/

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