简体   繁体   English

如何将列表从子类泛型转换为父类泛型?

[英]How do I cast a List from a subclass generic to a parent class generic?

I'm modifying open JDK to add features and I've run into this twice with no good solution. 我正在修改开放式JDK以添加功能,但是我遇到了两次都没有好的解决方案。

There's a class named JCStatement which extends JCTree . 有一个名为JCStatement的类,它扩展了JCTree

Issue: I want to cast a List<JCStatement> into a List<JCTree> . 问题:我想将List<JCStatement>转换为List<JCTree>

It's clear that a class can reference one of its extensions, but when I have it on a List, it just doesn't work. 显然,一个类可以引用其扩展名之一,但是当我将其放在List上时,它只是不起作用。

I used: (List<JCTree>)((List<?>)params) to cast, which works, but doesn't build on ant. 我曾经使用过: (List<JCTree>)((List<?>)params)进行(List<JCTree>)((List<?>)params) ,但不能在ant上构建。 IDE gives me the following warning: IDE给我以下警告:

Type safety: Unchecked cast from List<capture#1-of ?> to List<JCTree>

So this must be worked around somehow. 因此,这必须以某种方式解决。

I appreciate any help. 感谢您的帮助。

You cannot make this cast. 您无法进行此演员表转换。

What happens if you cast a List<JCStatement> to a List<JCTree> and then you add a JCTree (non JCStatement) object to that list? 如果将List<JCStatement>转换为List<JCTree> ,然后将JCTree(非JCStatement)对象添加到该列表,会发生什么情况? It breaks the List<JCStatement> type safety. 它破坏了List<JCStatement>类型的安全性。

If you know you won't add any elements to the list -- so it will be type-safe -- then Collections.unmodifiableList(List<? extends E>) will return a List<E> . 如果您知道不会将任何元素添加到列表中-这样它将是类型安全的-然后Collections.unmodifiableList(List<? extends E>)将返回List<E>

This is totally type-safe and legit, because it enforces the guarantee that you'll never add an illegal element to the list, and it's provided by the JDK. 这完全是类型安全和合法的,因为它强制保证您绝不会将非法元素添加到列表中,并且由JDK提供。

Would something like this work for you? 这样的事情对您有用吗?

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

class A {
}

class B extends A {
}

class C extends A {
}

public class Program {
    public static void foo(List<? extends A> list) {
    }

    public static void main(String[] args) {
        List<A> listA = new ArrayList<A>();
        List<B> listB = new ArrayList<B>();
        List<C> listC = new ArrayList<C>();
        List<? extends A> listX = (List<? extends A>) listB;
        List<? extends A> listY = (List<? extends A>) listC;

        foo(listA);
        foo(listB);
        foo(listC);
        foo(listX);
        foo(listY);
    }
}

This seems to be an issue with the List, or generic types collections as general. 这似乎是List或一般类型的通用类型集合的问题。

Simplest solution ever: 最简单的解决方案:

ListBuffer<JCTree> ls = new ListBuffer<JCTree>();
for(JCVariableDecl v : params){ ls.append(v); }
return ls.toList();

You can do it if you're really really sure it's safe by casting through the Raw Type 如果您真的很确定通过使用Raw Type进行转换,则可以这样做

List<Number> listA = new LinkedList<Number>();
List<Integer> listB = new LinkedList<Integer>();
listA = (List<Number>)(List) listB;

I cannot imagine myself ever thinking that's a good solution to a problem, but it will do what you want, and there are some irritating limitations to compile time generics :) 我无法想象自己曾经认为这是解决问题的好方法,但是它将满足您的要求,并且在编译时间泛型时有一些令人烦恼的限制:)

There will always be a warning for a Unsafe cast, because what you're doing is in fact unsafe. 对于不安全的演员表,总会有警告,因为您所做的实际上是不安全的。 There is no way for the compiler to make it safe, you have to be sure of that yourself. 编译器无法使其变得安全,您必须自己确保这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM