Java 为什么getConstructor反射api需要int.class参数?

Java 为什么getConstructor反射api需要int.class参数?,java,reflection,Java,Reflection,加载特定类(X)时,在每类型常量池中创建Class实例 javac编译此语法int.class指向Integer.TYPE指向的对象 在代码下面,访问类X的参数化(int)构造函数 Class c = X.class; Constructor cons = c.getConstructor(int.class); cons.newInstance(10); 在上面的代码中,我不理解int.class参数在幕后的作用 为什么getConstructor没有设计为接受String类型参数“int”

加载特定类(
X
)时,在每类型常量池中创建
Class
实例

javac
编译此语法
int.class
指向
Integer.TYPE
指向的对象

在代码下面,访问
类X
的参数化(
int
)构造函数

Class c = X.class;
Constructor cons = c.getConstructor(int.class);
cons.newInstance(10);
在上面的代码中,我不理解
int.class
参数在幕后的作用


为什么
getConstructor
没有设计为接受
String
类型参数“int”而不是
int.class
Class.forName()
的参数就是一个例子。

int.Class
而不是
Integer。TYPE
是java编译器替代的语法糖。一个
对象被简单地说成是一个包含关于代码内部结构的元信息的对象。但如果我们对此采取更抽象的观点,我们可以重用该类来表示
类型
原语
s、
接口
s,甚至
无效
——它不是一个类型,而是返回值为否的方法的标识符。像您的示例中一样,
的这种重用有很多优点;考虑下面的代码:

public class X {
    public static void main(String args[]) throws Exception {
        X myX = X.class.getConstructor().newInstance();
        X myBigX = X.class.getConstructor(Integer.class).newInstance(0xCEED);
        X mySmallX = X.class.getConstructor(int.class).newInstance(10);
    }

    public X() {
        System.out.println("parameterless constructor called");
    }

    public X(Integer bigInteger) {
        System.out.println("object integer constructor called");
    }

    public X(int smallInteger) {
        System.out.println("primitive integer constructor called");
    }
}

如果反射API开发人员为每个将
对象作为类型标识符的方法引入了反射API,则必须引入第二个反射API来处理不完全是
的类型,这将创建不必要的代码重复和不灵活。现在,为什么他们决定将
.class
附加到基元类型关键字以引用相应的
指针?正如一些人已经指出的那样,省略这一部分将导致进一步的混乱和语法错误。实际上,后缀只是在继续书写硬编码类型的模式。

首先,
类是一种专用于特定用途的类型。有很多类,我们可以简单地用
字符串
替换它们的实例,如果我们接受一点模糊性和可能的性能损失,它就会起作用。例如,为什么使用数字而不是包含其表示的
字符串
s,或者为什么使用
枚举
s而不是名称?因此,拥有专用类型的实例可以确保创建、查找、解析或获取该实例所需的任何操作已经成功执行

因此,如果有一个表示
int.Class
Class
对象,您就知道您引用的是一个现有的类型,这是关于
字符串
“int”
不能说的。
String
参数不一定引用现有类型-它甚至不必包含有效名称。如果您查找一个具有两个
int
参数的构造函数,那么传递
“int”,“int”
将意味着要完成整个验证正确性和两次查找适当类型的工作。等等

而且,由于Java编程语言的限制不适用于JVM,因此
字符串
是不明确的。尚不清楚
“int”
是指名为
int
,还是指原语类型
int
。请注意,当您在
类加载器上调用
loadClass(“int”)
时,总是假定您引用的是名为
int
类,因为该方法不适合查找基元类型。这就是为什么
int.class
被编译成访问
Integer.TYPE
,因为原语类型不能像引用类型那样被查找

此外,如前所述,名称在运行时是不明确的,因为可能有多个类具有相同的名称,由不同的
ClassLoader
s定义

见:

在运行时,类或接口不是由其名称单独决定的,而是由一对名称决定的:它的二进制名称()和它的定义类装入器

而且

行为良好的类装入器维护以下属性:

  • 给定相同的名称,一个好的类加载器应该总是返回相同的类对象

  • 如果类装入器L1将类C的装入委托给另一个装入器L2,则对于作为C的直接超类或直接超接口出现的任何类型T,或作为C中字段的类型出现的任何类型T,或作为C中方法或构造函数的形式参数的类型出现的任何类型T,或作为C中方法的返回类型出现的任何类型T,L1和L2应该返回相同的类对象

恶意类加载器可能会违反这些属性。但是,它不能破坏类型系统的安全性,因为Java虚拟机可以防止这种情况


请再次阅读问题可能重复的代码在
class X
中搜索构造函数,其中一个参数类型为
int
。“class”
Integer.TYPE
在这里指的是基元整数……为什么我们需要class文本语法作为参数?字符串“int”参数不够??问题是,为什么将
int.class
作为参数而不是
int
?我怀疑设计师们觉得在末尾添加
.class
更清楚地表明这是一个类型文字,而不是缺少括号或错误键入的变量的强制转换。