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

橙三吉。 提交于 2019-12-12 01:38:43

问题


I'm modifying open JDK to add features and I've run into this twice with no good solution.

There's a class named JCStatement which extends JCTree.

Issue: I want to cast a List<JCStatement> into a 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.

I used: (List<JCTree>)((List<?>)params) to cast, which works, but doesn't build on ant. IDE gives me the following warning:

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

So this must be worked around somehow.

I appreciate any help.


回答1:


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? It breaks the List<JCStatement> type safety.




回答2:


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>.

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.




回答3:


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);
    }
}



回答4:


This seems to be an issue with the List, or generic types collections as general.

Simplest solution ever:

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



回答5:


You can do it if you're really really sure it's safe by casting through the 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.



来源:https://stackoverflow.com/questions/10803005/how-do-i-cast-a-list-from-a-subclass-generic-to-a-parent-class-generic

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!