考虑以下通用转换器类(为简洁起见,简化/不完整)......
public abstract class BaseConverter <TModel>
{
public void convert(String data, Class<TModel> classOfModelType)
{
}
public void convert(String data)
{
convert(data, TModel.class); // This doesn't work!
}
}
在子类外部,我可以毫无问题地调用第一个convert
。考虑使用Car
作为泛型类型参数的此子类。我可以传递Car.class
,就像这样......
public class CarConverter extends BaseConverter<Car>
{
public void someFunction()
{
String someString;
convert(someString, Car.class);
}
}
我想要做的是尽可能多地移动到基类。由于'Car'在这里是已知的,因此convert
期望Car.class
,而TModel
代表基类中的Car
(无论如何对于这个具体的BaseConverter),我试图使用基类中的TModel.class
,但如上所述,它不起作用。
那么你如何在Java中实现这一目标呢?
答案 0 :(得分:3)
通过在Class
构造函数中接受它来存储对具体BaseConverter
的引用。像这样:
public abstract class BaseConverter <TModel>
{
private Class<TModel> clazz;
public BaseConverter(Class<TModel> clazz) {
this.clazz = clazz;
}
public void convert(String data, Class<TModel> classOfModelType)
{
}
public void convert(String data)
{
convert(data, clazz);
}
}
public class CarConverter extends BaseConverter<Car>
{
public CarConverter() {
super(Car.class);
}
public void someFunction()
{
String someString;
convert(someString, Car.class);
}
}
答案 1 :(得分:2)
这是Java中泛型的限制。泛型只存在于编译时,即在运行时对象只是BaseConverter
,因此您无法查询它的泛型类型。最简单的解决方案通常是在调用方法时传入Class<TModel>
对象(正如您所做)。如果您不想多次传递它,也可以将它传递给BaseConverter
的构造函数。
答案 2 :(得分:1)
在编译期间,泛型被擦除,并且在运行时不存在,因此T.class
是不可能的。如果您的代码中包含BaseConverter<T>
,那么它将在运行时变为BaseConverter<Object>
。
但你可以自己保存课程:
public abstract class BaseConverter <TModel> {
private final Class<TModel> clazz;
protected BaseConverter(Class<TModel> clazz) {
this.clazz = clazz;
}
public void someFunction()
{
String someString;
convert(someString, clazz); // use class here
}
}
public class CarConverter extends BaseConverter<Car> {
public CarConverter() {
super(Car.class);
}
}