通用java擦除如何影响newInstance()的使用?

通用java擦除如何影响newInstance()的使用?,java,generics,erasure,Java,Generics,Erasure,根据java文档: 在类型擦除过程中,Java编译器将擦除所有类型 如果类型为 参数是有界的,如果类型参数是无界的,则为对象 现在,问题是,对于这样一个类: public class MyCreator<T> { Class<T> kind; MyCreator(Class<T> kind) { this.kind = kind; } void printInstanceClass() throws E

根据java文档:

在类型擦除过程中,Java编译器将擦除所有类型 如果类型为 参数是有界的,如果类型参数是无界的,则为对象

现在,问题是,对于这样一个类:

public class MyCreator<T> { 
    Class<T> kind; 

    MyCreator(Class<T> kind) {
        this.kind = kind; 
    }

    void printInstanceClass() throws Exception{ 
        System.out.println(kind.newInstance().getClass());
    }

    public static void main(String[] args) throws Exception{ 
        MyCreator<String> myCreator = new MyCreator<String>(String.class);

        myCreator.printInstanceClass();
    } 
}
公共类MyCreator{
班级类型;
MyCreator(类类别){
this.kind=kind;
}
void printInstanceClass()引发异常{
System.out.println(kind.newInstance().getClass());
}
公共静态void main(字符串[]args)引发异常{
MyCreator MyCreator=新的MyCreator(String.class);
myCreator.printInstanceClass();
} 
}
printInstanceClass()
方法实际上正在打印“class java.lang.String”

如果编译器用Object替换类中的T,我猜与
kind
相关的类信息也会被删除并替换为class。那么,
newInstance()
方法如何返回字符串实例而不是对象实例呢?

传递String.class(它不是被擦除的,而是在运行时保留的一个具体类),然后在该类上调用newInstance,从而生成一个字符串

输出检查具体对象(字符串)并显示其类。

您传递String.class(它不会被擦除,但在运行时保留一个具体类),然后调用该类上的newInstance,从而生成一个字符串


输出检查具体对象(字符串)并显示其类。

棘手的部分是
String.class
参数。它不是一个类型参数,而是一个普通的旧参数,如
String[]args
。因此,
类种类
将是
String.Class
,因此
printInstanceClass()
可以在运行时访问它

这是一种常见的做法,也是在书中提出的

因此,在类型擦除之后,此代码在逻辑上等同于此代码:

public class MyCreator { 
    Class kind; // this will be String.class at runtime

    MyCreator(Class kind) {
        this.kind = kind; 
    }

    void printInstanceClass() throws Exception{ 
        System.out.println(kind.newInstance().getClass());
    }

    public static void main(String[] args) throws Exception{ 
        MyCreator myCreator = new MyCreator(String.class);

        myCreator.printInstanceClass();
    } 
}

棘手的部分是
String.class
参数。它不是一个类型参数,而是一个普通的旧参数,如
String[]args
。因此,
类种类
将是
String.Class
,因此
printInstanceClass()
可以在运行时访问它

这是一种常见的做法,也是在书中提出的

因此,在类型擦除之后,此代码在逻辑上等同于此代码:

public class MyCreator { 
    Class kind; // this will be String.class at runtime

    MyCreator(Class kind) {
        this.kind = kind; 
    }

    void printInstanceClass() throws Exception{ 
        System.out.println(kind.newInstance().getClass());
    }

    public static void main(String[] args) throws Exception{ 
        MyCreator myCreator = new MyCreator(String.class);

        myCreator.printInstanceClass();
    } 
}

将删除作为
myCreator
对象的泛型参数传递的类(类型)的相关信息,但不会删除
kind
对象中存储的信息

使用
Class
对象方法是可以的,但如果您试图从generic
T
类型获取类信息,则会遇到编译错误,例如:

void printInstanceClass() throws Exception{ 
    System.out.println(T.class.newInstance().getClass()); // error!
}

尽管这并不容易,但也存在执行上述操作的变通方法。

关于作为
myCreator
对象的泛型参数传递的类(类型)的信息会被删除,但存储在
类中的信息不会被删除

使用
Class
对象方法是可以的,但如果您试图从generic
T
类型获取类信息,则会遇到编译错误,例如:

void printInstanceClass() throws Exception{ 
    System.out.println(T.class.newInstance().getClass()); // error!
}

尽管这并不容易,但执行上述操作的变通方法也存在。

您的意思是,由于我们将类作为构造函数的参数传递,而不是通过泛型参数传递,因此编译器不会删除该类?确切地说,删除只影响类型参数,非具体对象您的意思是,由于我们将类作为构造函数的参数传递,而不是通过泛型参数传递,因此编译器不会删除该类?确切地说-删除只影响类型参数,而不是具体对象您应该尝试看看如果删除类型参数
t
,会发生什么情况,并使用
Class
作为原始类型。它仍将打印
class java.lang.String
,这意味着此信息不仅仅存储在类型参数中。如果删除类型参数
T
,并将
class
用作原始类型,您应该尝试看看会发生什么。它仍将打印
class java.lang.String
,这意味着此信息不仅仅存储在类型参数中。String.class返回类型class的实例。这不是类的子类型,因此您的代码不会编译。也许你想用类来代替?我的代码只是一个粗略的演示,演示了反编译编译后的代码会是什么样子。不管怎样,我应该更准确一点。用可编译的东西更新代码。因此,这个代码段和我发布的代码段之间的区别在于,带有类型参数的代码段允许将构造函数中传递的类与使该类特定的参数绑定在一起。正当没有泛型,我们可以传递构造函数中的任何类,使用泛型,我们可以控制要传递的内容,并根据泛型参数本身使类的行为不同。String.class返回class类型的实例。这不是类的子类型,因此您的代码不会编译。也许你想用类来代替?我的代码只是一个粗略的演示,演示了反编译编译后的代码会是什么样子。不管怎样,我应该更准确一点。用可编译的东西更新代码。因此,这个代码段和我发布的代码段之间的区别在于,带有类型参数的代码段允许将构造函数中传递的类与使该类特定的参数绑定在一起。正当没有泛型,我们可以传递构造函数中的任何类,使用泛型,我们可以控制要传递的内容,并根据泛型参数本身使类的行为不同。