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
更清楚地表明这是一个类型文字,而不是缺少括号或错误键入的变量的强制转换。