请考虑以下3个Java类:
超级课程:
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;
}
// ...
}
工作子类:
public class FloatColumn extends Column<Float>
{
public FloatColumn(String name)
{
super(Float.class, name);
}
// ...
}
有问题的子类:
public class ListColumn<L extends List<T>, T> extends Column<L>
{
public ListColumn(String name)
{
super((Class<L>) List.class, name);
}
// ...
}
有问题的子类(ListColumn
)在Eclipse中编译得很好,Java编译器合规性设置为1.6。但是,当通过Maven编译时(使用JDK编译器,源和目标设置为1.6),Inconvertible types
构造函数中super()
调用时出现ListColumn
错误。
编辑:Eclipse会警告此行(Type safety: Unchecked cast from Class<List> to Class<L>
)。
我知道Eclipse不使用JDL编译器,显然它使用的编译器不如JDK编译器严格。
但是,我的问题是如何使这个代码在1.6 JDK编译器上运行。
换句话说,如何使用符合预期Class<L>
类型的参数调用超级构造函数,其中L
仅限于extends List<T>
。
最好我只想在ListColumn
构造函数中进行更改,而不是在Column
类中进行更改。
答案 0 :(得分:2)
它可能对你有帮助。
super((Class<L>)(Class<?>)List.class, name);
注意:它显示警告,但您可以使用@SuppressWarnings("unchecked")
有关详细信息,请查看Class object of generic class (java)
答案 1 :(得分:0)
假设我按如下方式实例化你的类:
ListColumn<ArrayList<String>, String> listColumn = new ListColumn<ArrayList<String>, String>("column");
现在,您的代码会尝试将List.class
投射到Class<ArrayList>
,但事实并非如此。
如果您希望允许客户端使用Column
泛型类型的子类型,则可以在T
类中使用协方差。例如,将Column
构造函数更改为:
public Column(Class<? extends T> type, String name)
允许您在ListColumn
中调用super而不进行任何演员,因为现在允许List
的任何子类型,但是以类型安全方式。
至于欺骗编译器接受任何类型的泛型仅仅警告,你可以使用最脏的“双重投射”技巧,简单地消除泛型,因此编译器将不再能够赶上你的代码:
List<Integer> l = new ArrayList<Integer>();
List<String> s = (List<String>) (List) l;
但这真的是你想要的吗?