Java反射:Constructor.newInstance()分析
回想初学Java时好高骛远,连"Hello World"都打不明白的时候便想着解决反射,实在是惭愧惭愧
何为反射(reflection)
首先搬运一些百度上既有的答案:
反射(reflection):指的是在运行时通过反射 API 获取类的内部信息,并能直接操作任何对象的属性和方法。
当一个类被加载之后,这个类的信息保存在 Java 虚拟机的方法区中,这个类的对象实例则保存在虚拟机的堆中,通过方法区获取并操作一个类,就像是透过一面镜子反射到堆中的对象。JDK 提供了 java.lang.Class 类来支持反射机制。
这样一段话对初接触java,学习反射的人来说多少有点抽象了(自认为
因此流于表面的话:
// 正常创建对象,直接调用构造器
GetPortsInfo fpi = new GetPortsInfo("192.168.4.4","https://www.baidu.com");
// 反射创建对象,先单独获取构造器对象,然后再往里填入数据,如:
Class clazz = Class.forName("YiHuo.IkunScanner.GetPortsInfo"); // 获取类
Object o = clazz.getConstructor(String.class,String.class).newInstance("192.168.4.4","https://www.baidu.com"); // 获取该类中的构造器后再填入数据
newInstance()与new xxx()的作用是大同小异的,都是创建一个对象,这里进入newInstance方法中拉取源码去看看详细内容
@SuppressWarnings("all")
// 由于直接拉取源码粘贴出来会报错先全部忽略
@CallerSensitive
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, null, modifiers);
}
}
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");
ConstructorAccessor ca = constructorAccessor; // read volatile
if (ca == null) {
ca = acquireConstructorAccessor();
}
@SuppressWarnings("unchecked")
T inst = (T) ca.newInstance(initargs);
return inst;
}
在源码中可以看到,newInstance首先传入初始化变量,在方法中第一个if循环中首先判断传入的方法是否被重写(!override),该参数默认为false,在第二个if中将传入的类的修饰符转为1(true)与0(false)后与Modifier.ENUM(0x00004000)和运算后不为0即可,其实就是判断该类能否被外部引用,如果可以便创建一个构造器访问器,ConstructorAccessor被volatile所修饰。在完成上述一系列操作后,通过创建一个泛型对象inst承载实现了newInstance()接口方法而初始化的反射得到的构造器,再将其返回给外部方法中。
这就是反射中newInstance的具体实现过程
getModifiers()方法描述:
Returns the Java language modifiers for this class or interface, encoded in an integer. The modifiers consist of the Java Virtual Machine's constants for public, protected, private, final, static, abstract and interface; they should be decoded using the methods of class Modifier.
If the underlying class is an array class, then its public, private and protected modifiers are the same as those of its component type. If this Class represents a primitive type or void, its public modifier is always true, and its protected and private modifiers are always false. If this object represents an array class, a primitive type or void, then its final modifier is always true and its interface modifier is always false. The values of its other modifiers are not determined by this specification.
The modifier encodings are defined in The Java Virtual Machine Specification, table 4.1.
返回此类或接口的Java语言修饰符,以整数编码。修饰符由Java虚拟机的公共、受保护、私有、最终、静态、抽象和接口常量组成;它们应该使用类Modifier的方法进行解码。
如果基础类是数组类,那么它的public、private和protected修饰符与其组件类型的修饰符相同。如果这个类表示基元类型或void,那么它的公共修饰符总是true,而它的protected和private修饰符总是false。如果此对象表示数组类、基元类型或void,则其最终修饰符始终为true,其接口修饰符始终为false。其其他修改器的值不由本规范确定。
修改器编码在Java虚拟机规范表4.1中进行了定义。
结语
由于我实在是太懒了,估计对java反射篇的源码分析还要接近三个月的时间才能润色(可能鸽了,所以期间我会考虑发布一些更新手的知识分享(也可能鸽了,谢谢您的观看。
我是Dixk-BXy,新手上路,转载请注明原文链接:https://www.cnblogs.com/DenZi/articles/17628297.html