Domanda

Please consider the following 3 Java classes:

Super class:

public abstract class Column<T>
{

    private final Class<T> type;
    private final String name;


    public Column(Class<T> type, String name)
    {
        this.type = type;
        this.name = name;
    }

    public Class<T> getType()
    {
        return type;
    }

    // ...

}

Working subclass:

public class FloatColumn extends Column<Float>
{   

    public FloatColumn(String name)
    {
        super(Float.class, name);
    }

    // ...

}

Problematic subclass:

public class ListColumn<L extends List<T>, T> extends Column<L>
{   

    public ListColumn(String name)
    {
        super((Class<L>) List.class, name);
    }

    // ...

}

The problematic subclass (ListColumn) compiles fine in Eclipse, with Java compiler compliance set to 1.6. However, when compiled through Maven (using the JDK compiler, with source and target set to 1.6), I get an Inconvertible types error at the super() call in the ListColumn constructor.

Edit: Eclipse does warn about this line (Type safety: Unchecked cast from Class<List> to Class<L>).

I know that Eclipse does not use the JDL compiler, and apparently the compiler it does use is less strict than the JDK one.

However, my question is how can I make this code work on the 1.6 JDK compiler.

In other words, how can a I call the super constructor with an argument that conforms to the expected Class<L> type where L is restricted to extends List<T>.

Preferably I only want to make changes in the ListColumn constructor, not in the Column class.

È stato utile?

Soluzione

It might help you.

super((Class<L>)(Class<?>)List.class, name);

Note: It shows WARNING but you can suppress it using @SuppressWarnings("unchecked")


For more info have a look at Class object of generic class (java)

Altri suggerimenti

Assume I instantiate your class as follows:

ListColumn<ArrayList<String>, String> listColumn = new ListColumn<ArrayList<String>, String>("column");

Now, your code will try to cast List.class to a Class<ArrayList> which is not the case.

You can make use of covariance in your Column class if you want to allow clients to use subtypes of your T generic type. For instance, changing the Column constructor to:

public Column(Class<? extends T> type, String name)

would allow you to call super in your ListColumn without any cast, since any subtype of List would now be allowed, but in a type safe manner.

As for tricking the compiler to accept any sort of generics cast with a mere warning, you can use the most dirty "double cast" trick that simply eliminates generics so the compiler won't catch up with your code anymore:

List<Integer> l = new ArrayList<Integer>();
List<String> s = (List<String>) (List) l;

But is that really what you want ?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top