无法将ArrayList<subtype>转换为ArrayList<type>。

3
我正在编写一个程序来模拟人工神经网络。我已经设置了以下类和接口:
public interface Neuron
{
}

// Input neuron
public class INeuron implements Neuron
{
}

// Output and hidden neuron
public class ONeuron implements Neuron
{
}

public interface Layer
{
    public ArrayList<Neuron> getNeurons();
}

// Input layer
public class ILayer implements Layer
{
    ArrayList<INeuron> neurons = new ArrayList<INeuron>();

    public ArrayList<Neuron> getNeurons()
    {
        return neurons;
    }

    // other stuff appropriate to the input layer
}

编译器报错:"无法将ArrayList<INeuron>转换为ArrayList<Neuron>。"

我尝试过调整代码,比如:ArrayList<Neuron> neurons = new ArrayList<INeuron>()。但是这似乎只是把同样的错误转移到类的其他部分。

我不明白为什么INeuron不能隐式转换为Neuron,因为INeuron是Neuron的子类型。


正确的解决方案将取决于您对返回列表的预期使用(仅读取?修改?)。Generic<SubType>Generic<Type>之间有很好的理由不相同。 - trutheality
4个回答

8

你需要使用:

public interface Layer
{
    public ArrayList<? extends Neuron> getNeurons();
}

由于泛型中缺乏协变和逆变,如果您将一个ArrayList < INeuron > 作为ArrayList < Neuron > 返回,则可能会向ArrayList < INeuron > 添加一个不是INeuron(如另一个Neuron的子项)的元素。


4

只需更改:

ArrayList<INeuron> neurons = new ArrayList<INeuron>();

to:

ArrayList<Neuron> neurons = new ArrayList<Neuron>();

为了能够同时服务这两种类型。


2

这是一个不好的事情的示例。

void mymethod ( ILayer l )
{
     List<Neuron> neurons = l . getNeurons ( ) ;
     neurons . add ( new ONeuron ( ) ) ; // bad thing
}

我的方法mymethod刚刚使那个ILayerneurons列表受到了非INeuron的污染。
我推荐使用Luciano的解决方案

很好的发现!这是为了一个课程(我是老师)。我们下周将更改API以使用迭代器。 - Barry Brown
@BarryBrown 你也需要处理迭代器的同类问题。 - trutheality
是的,我看到了... 有更好的解决方案吗? - Barry Brown
正如trutheality所说:“正确的解决方案将取决于您对返回列表的预期用途”。根据您的代码示例,我建议使用Luciano的解决方案。为什么那个不令人满意呢? - emory

0
public Layer <?> getNeurons();

这是另一种写子类型的方式,对吧?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接