【问题标题】:generics, method signatures, assignments泛型、方法签名、赋值
【发布时间】:2010-02-18 21:24:47
【问题描述】:

我以为我明白这一点,但显然不是......

我有一个这样的方法签名:

void doSomething(List<TypeA> typeAs){...}

List<TypeA<TypeB>> getTypeBTypeAs(){...}

但如果我试着打电话

doSomething(getTypeBTypeAs());

我得到一个编译错误:“类型...中的方法 doSomething(List) 不适用于参数 (List>)”

但是,如果我将doSomething 的签名更改为

void doSomething(List<TypeA<?>> typeAs){...}

还是不行,但是

void doSomething(List typeAs){...}

显然它可以在我绕过泛型时起作用。

这看起来很奇怪。

有人可以填写吗?

另外,在这种情况下,我希望doSomething 可以处理包含任何泛型类型的 TypeAs 的任何 List;未定义、TypeB、TypeC 等。

谢谢。

【问题讨论】:

    标签: java generics


    【解决方案1】:

    泛型类TypeA<TypeB> 是与TypeA 不同的类型。您不能传入TypeA<TypeB> 类型的参数,而该方法需要TypeA。此外,TypeA<TypeB>TypeA<TypeC> 的类型不同,因此适用相同的约束。

    经典的例子(来自Effective Java, 2nd Ed.AFAIR)是:我们有动物容器(Container<Animal>),作为Animal的子类,我们有LionButterfly。现在,如果你有一个方法

    void func(Animal animal);
    

    它将接受狮子和蝴蝶。不过这个功能

    void func(Container<Animal> animalContainer);
    

    不接受Container&lt;Lion&gt;,也不接受Container&lt;Butterfly&gt;。请务必意识到,用于安全保护狮子的坚固笼子不会阻止蝴蝶飞走,反之亦然,用于容纳蝴蝶的厚而轻的网将无法对抗狮子。

    如果你真的确定任何种类的动物容器都适合你,请像这样声明你的函数:

    void func(Container<? extends Animal> animalContainer);
    

    回到你的情况,我想接受List&lt;TypeA&gt;List&lt;TypeA&lt;TypeB&gt;&gt; 的唯一方法是这样的:

    void doSomething(List<?> list);
    

    【讨论】:

    • 如果 Effective Java 有泛型示例,那一定是第二版,因为我的办公桌上放着第一版,比 Java 5 早几年。
    • 是的,它在第二版中。并且它可以在线获得,谷歌它(有效的 Java 泛型)
    • 另外,如果你确实想让第二个函数接受一个包含任何动物的容器,它会是void func(Container&lt;? extends Animal&gt; animalContainer);,不是吗?
    • 那么我该如何设置一个方法,即doSomething 来接受包含List&lt;TypeA&gt; 的任何化身的列表?
    • 感谢大家的cmets,我添加了本书的链接。 @R。 Bemrose 如果有机会,我同时添加了相同的解决方案 :-)
    【解决方案2】:

    试试这个:

    <T> void doSomething(List<TypeA<T>> typeAs) { ... }
    

    注意行首的&lt;T&gt;。这样 doSomething 接受每个包含任何 TypeAs 的 List。

    【讨论】:

    • 你说得对,现在我明白你所说的“未定义”是什么意思了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-05
    • 2013-12-18
    • 1970-01-01
    • 1970-01-01
    • 2014-04-21
    相关资源
    最近更新 更多