4

我在返回通用列表的方法时遇到了一些问题。代码基本上是这样的:

public class MyClass{
    private List<MyListElement> myList = new ArrayList<MyListElement>();

    public <E> List<E> getGenericList(){
        return new ArrayList<E>();
    }

    public void thisWorks(){
        List<MyListElement> newList = getGenericList();
        myList.addAll(newList);
    }

    public void thisDoesntWork(){
        myList.addAll(getGenericList());
    }

    public void thisDoesntWorkEither(){
        for(MyListElement elem : getGenericList()){
            fiddle();
        }
    }
}

为什么该thisDoesntWork()方法不起作用,是否有任何其他方法可以解决它(除了thisWorks()以并不总是实用的方式进行操作)?

4

4 回答 4

7

编译器无法推断为<E>中的泛型方法getGenericList()的类型参数选择什么类型thisDoesntWork()

在这种情况下,您需要通过调用显式声明类型参数的类型<MyListElement>getGenericList()

或者,您可以更改签名getGenericList()以接受Class<E>参数。getGenericList(MyListElement.class)然后你会同时调用thisWorks()and thisDoesntWork()。诚然,这有点冗长,但对于您的方法的客户来说肯定更直观。

作为一般规则,我想说的是,尝试使泛型方法的类型参数可以从该方法的参数中推断出来。

于 2012-12-17T21:26:11.073 回答
3

你可以thisDoesntWork()这样改变:

  public void thisDoesntWork(){ // well, it works now
      myList.addAll(this.<String>getGenericList());
  }

您需要告诉编译器getGenericList()正在处理什么类型。

于 2012-12-17T21:25:34.023 回答
3

泛型方法的类型参数<E> getGenericsList()可以在调用时传递:

this.<String>getGenericsList()

否则编译器会尽力从上下文中推断出来。当您将返回的对象分配给List<String>引用时,编译器因此推断您String作为类型参数传递。

给定列表 API

List<E> {
  void addAll(Collection<? extends E> c);
}

编译器似乎无法推断出正确的类型,老实说我不知道​​这是因为它不够聪明,还是因为它不想通过设计承担责任。

我什至做了一个测试,看看问题是否出在通配符上,或者是否addAll()无法从参数化类型推断类型参数,但似乎没有任何效果:

public class GenericsList {

    public static void main(String[] args) {
        // same signature as Java API
        List<String> base = new List<String>();
        base.addAll(GenericsList.getList()); // ERROR!

        // addAll() doesn't use a wildcard
        List2<String> base2 = new List2<String>();
        base2.addAll(getList2()); // ERROR!

        // what about a generic method?
        addAll(base, getList()); // ERROR!
    }

    static <E> List<E> getList() {
        return new List<E>();
    }

    static <E> void addAll(List<E> src, List<E> other) {}

    static <E> List2<E> getList2() {
        return new List2<E>();
    }

    static class List<E> {
        void addAll(List<? extends E> other) {}
    }

    static class List2<E> {
        void addAll(List2<E> other) {}
    }

}
于 2012-12-17T21:46:26.087 回答
0

此代码将为您工作。 getGenericList()应该知道它返回的是什么,并且应该与您的列表类型兼容。

您无需将其转换为 String 或其他人建议的任何其他内容,因为它将通过将其绑定到字符串类型来限制您的 getGenericList 方法意图。

public class MyClass{
    private List<MyListElement> myList = new ArrayList<MyListElement>();

    public <E extends MyListElement> List<E> getGenericList(){
        return new ArrayList<E>();
    }

    public void thisWorks(){
        List<MyListElement> newList = getGenericList();
        myList.addAll(newList);
    }

    public void thisDoesntWork(){
        myList.addAll(getGenericList());
    }

    public void thisDoesntWorkEither(){
        for(MyListElement elem : getGenericList()){
            fiddle();
        }
    }
}
于 2012-12-18T07:06:15.440 回答