代码之家  ›  专栏  ›  技术社区  ›  Nick

Java泛型-预期返回类型不同于实际

  •  5
  • Nick  · 技术社区  · 14 年前

    下面是我正在处理的一些代码的示例:

    public interface FooMaker<T extends Enum<T> & FooType>
    {
          public List<Foo<T>> getFoos(String bar);
    }
    

    让我们进一步假设Foomaker有许多不同的具体实现。所以我写了一些代码来使用foomakers。

    FooMaker<?> maker = Foos.getRandomMaker();
    List<Foo<?>> fooList = maker.getFoos("bar");  //error here!
    

    第二行代码导致了这个问题,Eclipse告诉我代码应该是:

    FooMaker<?> maker = Foos.getRandomMaker();
    List<?> fooList = maker.getFoos("bar");
    

    我很难理解为什么作为列表中的参数化类型的foo声明必须消失才能使返回类型正确。

    有什么想法吗?

    3 回复  |  直到 14 年前
        1
  •  1
  •   Luke Hutteman    14 年前

    试试这个:

    List<? extends Foo<? extends Enum<?>>> fooList = maker.getFoos("bar");
    

    问题是,如果允许这样做:

    List<Foo<?>> fooList = maker.getFoos("bar");
    

    如果再延长一段时间,你也可以摆脱这个问题:

    Foo<?> foo1 = new Foo<String>();
    Foo<?> foo2 = new Foo<Integer>();
    fooList.add(foo1);
    fooList.add(foo2);
    

    这将使返回列表的通用合同无效。

    为了防止这种情况,Java编译器强制返回类型是基于通配符的,这意味着Foo可以用作返回类型(将元素从列表中拉出来),但是不能将通配符为基础的FO类型添加到列表中。

        2
  •  1
  •   Tom Hawtin - tackline    14 年前

    通常的:

    class Bar {}
    class Baz {}
    
    FooMaker<?> maker = new FooMaker<Bar>();
    List<Foo<?>> fooList = maker.getFoos("bar");  //error here!
    fooList.add(new Foo<Baz>());                  //cock-up here!
    
        3
  •  0
  •   matt b    14 年前

    因为你要申报 maker 作为 FooMaker<?> . 你为什么不把它声明为 AwesomeFooMaker 如果你知道具体是什么 T 冬虫夏草 返回?