Take the 2-minute tour ×

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.

share|improve this question
you cannot use typecasting, there are methods that can help you, for example Collections.copy(List dest, List src). Find these methods and choose the best for you. Sorry for bad answer, cannot find them at this moment –  alaster May 29 '12 at 16:28
I edited this to remove the extra example, which was un-necessary, and to cleanup the title question. –  Erick Robertson May 29 '12 at 16:39
alaster, your solution almost worked, but I'd need a way to instantiate a List<JCTree> with enough space for the copy, List.nil() doesn't work. –  Adriano May 29 '12 at 16:51

5 Answers 5

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.

share|improve this answer
+1 Edited for clarity. If OP explains why he thinks this is the solution, we can try to help him find a better solution. He hasn't provided enough information for us to know the way to solve the problem. –  Erick Robertson May 29 '12 at 16:43
There are no other objects I'm supposed to insert into the List, adding one would probably break the compiler in some point. –  Adriano May 29 '12 at 16:53

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;

share|improve this answer
No, even worse: The method appendList(List<JCTree>) in the type ListBuffer<JCTree> is not applicable for the arguments (List<capture#2- of ? extends JCTree>) –  Adriano May 29 '12 at 16:35
Oh sorry, I didn't realize that you don't have any control over the method signature in this case. My code sample would work if you were able to change the method signature to accept a List<? extends JCTree> instead of List<JCTree>. I'll leave this answer here just in case someone's finds it helpful. –  William Brendel May 29 '12 at 16:42
up vote 1 down vote accepted

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();
share|improve this answer

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.

share|improve this answer

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.

share|improve this answer

Your Answer


