Java 什么';是泛型类中T.class的等价物吗?

Java 什么';是泛型类中T.class的等价物吗?,java,class,generics,Java,Class,Generics,考虑以下通用转换器类(为简洁起见,简化/不完整) 我想做的是尽可能多地移动到基类。由于“Car”在这里是已知的,因此convert期望Car.class,而TModel在基类中表示Car(无论如何,对于这个具体的基类转换器),所以我试图在基类中使用TModel.class,但如上所述,它不起作用 那么如何在Java中实现这一点呢?这是Java中泛型的一个限制。泛型仅在编译时存在,即在运行时,对象只是一个BaseConverter,因此您无法查询它的泛型类型。最简单的解决方案通常是在调用方法时传入

考虑以下通用转换器类(为简洁起见,简化/不完整)

我想做的是尽可能多地移动到基类。由于“Car”在这里是已知的,因此
convert
期望
Car.class
,而
TModel
在基类中表示
Car
(无论如何,对于这个具体的基类转换器),所以我试图在基类中使用
TModel.class
,但如上所述,它不起作用


那么如何在Java中实现这一点呢?

这是Java中泛型的一个限制。泛型仅在编译时存在,即在运行时,对象只是一个
BaseConverter
,因此您无法查询它的泛型类型。最简单的解决方案通常是在调用方法时传入一个
对象(正如您所做的那样)。如果不想多次传递,也可以将其传递给
BaseConverter
的构造函数。

通过在
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);
    }
}
公共抽象类BaseConverter
{
私人课堂;
公共基带转换器(clazz类){
this.clazz=clazz;
}
公共void转换(字符串数据、类classOfModelType)
{
}
公共void转换(字符串数据)
{
转换(数据、分类);
}
}
公共类CarConverter扩展了BaseConverter
{
公营车辆转换器(){
超级(汽车级);
}
公共函数()
{
字符串;字符串;
转换(someString,Car.class);
}
}
泛型在编译期间被擦除,在运行时不存在,因此
T.class
不可能执行。如果代码中有
BaseConverter
,它将在运行时变为
BaseConverter

但您可以自己保存该类:

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);
    }
}
公共抽象类BaseConverter{
私人期末班;
受保护的BaseConverter(clazz类){
this.clazz=clazz;
}
公共函数()
{
字符串;字符串;
convert(someString,clazz);//在此处使用类
}
}
公共类CarConverter扩展了BaseConverter{
公营车辆转换器(){
超级(汽车级);
}
}

我认为没有类似的方法。类型在编译时未知,那么编译器将替换什么?如果在
convert
中传入类类型,为什么不使用相同的技术呢?向ctor添加一个类类型,它将为转换器提供一个基类。。。它在编译时是已知的。例如,如果我在BaseConverter中添加一个返回TModel的函数,如果您查看子类上的签名,它将返回Car,因为编译器知道该类型。关键是编译器确实知道传递给它的是什么,否则它无法解析任何用法。其他语言允许这样做。我猜这只是Java的一个局限性。实际上,我认为第二个
convert
方法要实现的就是第一个
convert
方法所要实现的。
将是子类的泛型类型参数的
对象。可能您希望在第一个
转换
中实现的应该是:
公共无效转换(字符串数据,类,但TModel不只是类型的占位符吗?如何扩展实际上不存在的东西?我承认我是Java新手,所以我不确定这是什么,因为我以前从未见过“?扩展TModel”。这很令人沮丧,因为正如你所说,在运行时它被编译为BaseConverter,基本上用Car替换TModel换句话说,如果有四个子类传入四种不同的TModel类型,那么最终会得到四个具体的类(即所有类型在编译时都是已知的)而泛型实际上并不存在于任何地方。在这种情况下,为什么它不能在编译时获取类,这是我无法理解的,也是非常令人沮丧的。你没有得到4个类,但只有一个:其中
TModel
Object
替换。因此初始类型信息丢失(实际术语被删除)它不能被还原。是的,我刚刚读到了。这就是Java与其他语言的不同之处,泛型是一流的公民。你最终得到了四种新的具体类型。令人失望的是,他们在Java中实现了它,而事情却被破坏了。虽然我知道我可以做到这一点,但我很欣赏我的c然后在其他CAL中省略它,我试图从泛型的类型尽可能多地推断,这样我就不必这么做了。毕竟,在编译时,它会在内部知道它们是汽车类型,所以它怎么能不知道汽车类呢?其他语言允许这种事情,所以它看起来是Java编译器/语言的限制,而不是e泛型本身的设计。在编译时,在
BaseConverter
中,它只知道泛型类型
TModel
。为什么编译器会认为
TModel
=
Car
?毕竟,它不像
CarConverter
是唯一可以扩展
BaseConverter
的类。但这就是它……编译器(其他语文)不是编译TModel。他们正在编译Car和所有其他实例。如果你创建一个泛型的十个子类,指定十个不同的类型参数,你最终会得到十个具体的类型,同样,在其他语言中。我今天才发现Java的类型擦除,在我刚才描述的例子中,你只有一个类型,而不是t嗯,TModel本质上被改为Object。这是丢失的信息。我错误地认为,就像在其他语言中一样,Java也做了同样的事情,但它没有。
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);
    }
}
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);
    }
}