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

发布于 2025-01-03 12:37:48 字数 396 浏览 1 评论 0原文

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

如果相关的话,在我的例子中,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,但我不知道这是否是最好的选择,因为我可以接收任何类型的列表。

I have a list, and I need to return that same type of list.

If it's relevant, in my case Y is an interface and interface X is its superinterface.

I assume that I need to use newInstance to get the type of 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;
}

I could just make an ArrayList, but I don't know if that's the best thing to do since I could receive any type of list.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

属性 2025-01-10 12:37:48

您是否将 List 的类与其泛型类型混淆了?很少需要返回List的特定实现(例如,如果它需要可序列化)。我建议只使用 ArrayList,并预先调整好大小。

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

Are you mixing up the class of the List with its generic type? There should rarely be any need to return a particular implementation of List (e.g., if it needs to be serializable). I recommend just using an ArrayList, sized appropriately beforehand.

With regards to the interfaces, be careful because if Y extends X, you can't in general put objects from xList in yList (I assume you want to), because there might be an instance of X in the list that isn't a Y.

若无相欠,怎会相见 2025-01-10 12:37:48

Java 通过擦除实现泛型,因此在运行时您将看不到 List.getClass()List.getClass() 之间的区别;。但是,您应该能够说:

List<Y> yList = new ArrayList<Y>(); // Or LinkedList, or whatever implementation you want.

如果您不知道要使用哪个 List 实现,而这正是您想要依赖于支持 xList 的列表类型的实现,您仍然可以使用 newInstance:你只需要转换它:

List<Y> yList = (List<Y>)xList.getClass().newInstance();

在运行时,你所拥有的只是一个 LinkedListArrayList 或类似的东西,但只要你不要将任何非 Y 项目添加到列表中,您应该可以安全地将其作为 List 返回。

Java implements generics via erasure, so at runtime you will see no difference between the .getClass() of a List<X> and that of a List<Y>. However, you should be able to just say:

List<Y> yList = new ArrayList<Y>(); // Or LinkedList, or whatever implementation you want.

If you don't know which List implementation to use, and that's what you want to have depend on the list type backing xList, you can still use newInstance: you just have to cast it:

List<Y> yList = (List<Y>)xList.getClass().newInstance();

At runtime, all you'll have is a LinkedList or ArrayList or some such, but as long as you don't add any non-Y items to the list, you should be safe returning it as a List<Y>.

情绪失控 2025-01-10 12:37:48

由于您不知道 List 的类型,因此您也不知道它是否有公共无参数构造函数,因此您无法确定 newInstance() 不会抛出异常。

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

List<Y> yList = (List) xList;

Since you don't know the type of the List, you don't know if it has a public no-arg constructor either, so you can't be sure that newInstance() won't throw an exception.

If you don't want a copy of the list, and you know that the list actually contains Y instances, you could just do

List<Y> yList = (List) xList;
梦太阳 2025-01-10 12:37:48
List<Y> yList = (List<Y>) xList.getClass().newInstance();

仅当无参数构造函数可用时才有效。如果它不可访问,您可能需要使用反射覆盖访问可见性:

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

如果该类没有可用的无参数构造函数,那么您可能不走运!
建议实现类时提供以下形式的构造函数:

public MyListClass(Collection<T> items)

如果存在这样的构造函数,您可以尝试使用反射调用该构造函数并向其传递一个空列表。在一般情况下,不可能确定调用哪个构造函数:(

List<Y> yList = (List<Y>) xList.getClass().newInstance();

will work only if the no-args constructor is available. If it is not accessible, you may need to override the access visibility using reflection:

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

If there is no no-args constructor available for the Class, then you are probably out of luck!
It is advised for implementing classes to provide a constructor of the form:

public MyListClass(Collection<T> items)

If such a constructor exists, you may try invoking that constructor using reflection and passing it an empty List. It will not be possible, in the general case, to determine which constructor to call :(

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文