如何在Java中创建另一个List,给定一个List,但列出了不同的类

时间:2012-02-07 18:04:46

标签: java list generics instance

我有一个列表,我需要返回相同类型的列表。

如果它是相关的,在我的情况下,Y是一个接口,接口X是它的超级接口。

我假设我需要使用newInstance来获取List的类型。

public List<Y> foo() {
    List<X> xList = -a method that returns List<X>-;
    List<Y> yList = xList.getClass().newInstance(); //Is this right?

    ...

    return yList;
}

我可以制作一个ArrayList,但我不知道这是否是最好的事情,因为我可以收到任何类型的列表。

4 个答案:

答案 0 :(得分:1)

您是否将List的类与其泛型类型混合在一起?应该很少需要返回List的特定实现(例如,如果它需要可序列化)。我建议您事先使用适当大小的ArrayList

关于接口,请注意,因为如果Y扩展X,您通常无法将xList中的对象放入yList(我假设您需要) to),因为列表中可能有X的实例不是Y

答案 1 :(得分:0)

Java通过擦除实现泛型,因此在运行时,您会发现.getClass()的{​​{1}}与List<X>的{​​{1}}之间没有区别。但是,您应该只能说:

List<Y>

如果您不知道要使用哪个List实现,并且您希望依赖于支持List<Y> yList = new ArrayList<Y>(); // Or LinkedList, or whatever implementation you want. 的列表类型,您仍然可以使用xList:您只需要使用它:

newInstance

在运行时,你所拥有的只是List<Y> yList = (List<Y>)xList.getClass().newInstance(); LinkedList或其他一些,但只要你不在列表中添加任何非Y项,你就应该是安全的将其作为ArrayList返回。

答案 2 :(得分:0)

由于你不知道List的类型,你不知道它是否也有一个公共的无参数构造函数,所以你不能确定newInstance()不会抛出异常。 / p>

如果您不想要列表的副本,并且您知道该列表实际上包含Y个实例,那么您可以这样做

List<Y> yList = (List) xList;

答案 3 :(得分:0)

List<Y> yList = (List<Y>) xList.getClass().newInstance();
仅当no-args构造函数可用时,

才有效。如果无法访问,您可能需要使用反射覆盖访问可见性:

final Constructor cons = xList.getClass().getDeclaredConstructor();
cons.setAccessible(true);
List<Y> yList = (List<Y>) cons.newInstance();

如果Class没有no-args构造函数,那么你可能运气不好! 建议实现类以提供以下形式的构造函数:

public MyListClass(Collection<T> items)

如果存在这样的构造函数,您可以尝试使用反射调用该构造函数并将其传递给空List。在一般情况下,无法确定要调用的构造函数:(