实例化对象,其中构造函数采用Java中的抽象参数化类型



我有类似于下面所示的类,并且需要在第(*(行实例化一个Container对象。

public abstract class Foo {
...
}
public class Bar extends Foo {
...
}
public class Container {
public Container(ArrayList<Foo> fooList) {
this.fooList = fooList;
}
...
private ArrayList<Foo> fooList;
}
public static void main(String[] args) {
ArrayList<Bar> barList = new ArrayList<Bar>();
(*) Container container = new Container(barList);
}

然而,我得到以下编译错误:

error: incompatible types: ArrayList<Bar> cannot be converted to ArrayList<Foo>

有解决办法吗?我需要Container能够接受扩展Foo的不同子类的ArrayList。

更改Container类和main()方法,如下所示。

class Container {
public Container(List<Foo> fooList) {
this.fooList = fooList;
}
private List<Foo> fooList;
}
public class Solution {
public static void main(String[] args) {
List<Foo> barList = new ArrayList<>();
barList.add(new Bar());
Container container = new Container(barList);
}
}

如果由于任何原因无法更改Container类,唯一的解决方案是:

public static void main(String[] args) {
ArrayList<Foo> barList = new ArrayList<Foo>();
barList.add(new Bar());
Container container = new Container(barList);
}

然而,这是一个相当糟糕的设计,原因有三:

  1. Container类强制使用ArrayList而不是List接口的其他实现
  2. Container类强制使用Foo实例列表,不接受Foo的子类列表
  3. Container类可以存储Foo的任何描述符,并且它是不可配置的

第一个问题可以通过将ArrayList更改为List来解决。

public class Container {
public Container(List<Foo> fooList) {
this.fooList = fooList;
}
private List<Foo> fooList;
}

第二个问题可以通过使用Generics 来解决

public class Container {
public Container(List<? extends Foo> fooList) {
this.fooList = fooList;
}
private List<? extends Foo> fooList;
}

最后一个问题可以通过参数化Container类本身来解决:

public class Container<T extends Foo> {
public Container(List<? extends T> fooList) {
this.fooList = fooList;
}
private List<? extends T> fooList;
}
public static void main(String[] args) {
ArrayList<Bar> barList = new ArrayList<>();
Container<Foo> container = new Container<>(barList);
}

如果您想确保特定的列表实现将具有快速的O(1)通过索引获取操作,那么您只能接受同时实现ListRandomAccess接口的类。

public class Container {
public <L extends List<? extends Foo> & RandomAccess> Container(L fooList) {
this.fooList = fooList;
}
private List<? extends Foo> fooList;
}

最新更新