java:当SomeClass实现SomeInterface时,从List <SomeClass>转换为List <SomeInterface>

Jas*_*n S 8 java generics

我有一个大脑抽筋:我有一个public interface SomeInterfacestatic private class SomeClass我正在尝试List<SomeInterface>从我的一个方法返回一个,但我得到错误(在return list;下面的行):

Type mismatch: cannot convert from List<GenericList1.SomeClass> to
List<GenericList1.SomeInterface>
Run Code Online (Sandbox Code Playgroud)

如何在不创建新列表的情况下解决此问题?

澄清:我不希望将列表创建为List<SomeInterface>(可能是显而易见的解决方案),因为私下我想维护一个List<SomeClass>允许将来访问SomeClass的方法,而不是公共接口中的方法.这在下面的示例中没有显示,但在我的真实程序中我需要这个.

import java.util.ArrayList;
import java.util.List;

public class GenericList1 {

    public interface SomeInterface
    {
        public int getX();
    }

    private static class SomeClass implements SomeInterface
    {
        final private int x;
        @Override public int getX() {
            return this.x;
        }       
        public SomeClass(int x) { this.x = x; }
    }

    public static void main(String[] args) {
        List<SomeInterface> list = createList(10);
        printList(list);
    }

    private static void printList(List<SomeInterface> list) {
        for (SomeInterface si : list)
            System.out.println(si.getX());
    }

    private static List<SomeInterface> createList(int n) {
        List<SomeClass> list = new ArrayList<SomeClass>();
        for (int i = 0; i < n; ++i)
            list.add(new SomeClass(i));
        return list;
    }
}
Run Code Online (Sandbox Code Playgroud)

Pét*_*rök 24

您应该将方法重新定义为

private static List<? extends SomeInterface> createList(int n) { ...
Run Code Online (Sandbox Code Playgroud)

同样,其他列表声明.这允许您以多态方式处理通用列表,只要您只读取它们的值.

(如果要将新元素添加到列表中,则应使用List<? super SomeInterface>.)

这个成语以缩写PECS - Producer:Extends/Consumer:Super,由Josh Bloch在Effective Java 2nd Edition,Item 28中创造.

正如其他人指出,需要这个成语,因为List<SomeClass>不是一个List<SomeInterface>,甚至当SomeClass implements SomeInterface.其原因在参考文献中有详尽解释.


pnt*_*pnt 6

与流行的看法相反,即使是,List<Derived>也绝对没有关系.List<Base>Derived extends Base

仅仅因为类共享层次结构并不意味着它们的集合可以.一般来说,这对于仿制药来说都是如此.

您可以按如下方式更改代码:

private static List<SomeInterface> createList(int n) {
        List<SomeInterface> list = new ArrayList<SomeInterface>();
        for (int i = 0; i < n; ++i)
            list.add(new SomeClass(i)); //add a SomeClass object - valid, because it has the interface
    return list;
}
Run Code Online (Sandbox Code Playgroud)