深入理解Java中的反射机制和使用原理!详细解析invoke方法的执行和使用 (3)

从类中获取一个方法后,可以使用invoke() 来调用这个方法

public Object invoke(Object obj, Object ... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {}

示例:

public class InvokeTest { public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { Class<?> klass = method.class; // 创建methodClass的实例 Object obj = klass.newInstance(); // 获取methodClass的add方法 Method method = klass.getMethod("add", int.class, int.class); // 调用method对应的方法,实现add(1,4) Object result = method.invoke(obj, 1, 4); System.out.println(result); } } class methodClass { public final int n = 3; public int add(int a, int b) { return a + b; } public int sub(int a,int b) { return a * b; } } 利用反射创建数组

数组是Java中一种特殊的数据类型,可以赋值给一个Object Reference

利用反射创建数组的示例:

public static void ArrayTest() throws ClassNotFoundException { Class<?> cls = class.forName("java.lang.String"); Object array = Array.newInstance(cls, 25); // 在数组中添加数据 Array.set(array, 0, "C"); Array.set(array, 1, "Java"); Array.set(array, 2, "Python"); Array.set(array, 3, "Scala"); Array.set(array, 4, "Docker"); // 获取数据中的某一项内容 System.out.println(Array.get(array, 3)); }

Array类是java.lang.reflect.Array类,通过Array.newInstance() 创建数组对象:

public static Object newInstance(Class<?> componentType, int length) throws NegativeArraySizeException { return newArray(componentType, length); }

newArray方法是一个native方法,具体实现在HotSpot JVM中,源码如下:

private static native Object newArray(Class<?> componentType, int length) throws NegativeArraySizeException; ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - newArray源码目录: openjdk\hotspot\src\share\vm\runtime\reflection.cpp arrayOop Reflection::reflect_new_array(oop element_mirror, jint length, TRAPS) { if (element_mirror == NULL) { THROW_0(vmSymbols::java_lang_NullPointerException()); } if (length < 0) { THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); } if (java_lang_Class::is_primitive(element_mirror)) { Klass* tak = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL); return TypeArrayKlass::cast(tak)->allocate(length, THREAD); } else { Klass* k = java_lang_Class::as_Klass(element_mirror); if (k->oop_is_array() && ArrayKlass::cast(k)->dimension() >= MAX_DIM) { THROW_0(vmSymbols::java_lang_IllegalArgumentException()); } return oopFactory::new_objArray(k, length, THREAD); } }

Array类的setget方法都是native方法,具体实现在HotSpot JVM中,对应关系如下:

set: Reflection::array_set

get: Reflection::array_get

invoke方法

在Java中很多方法都会调用invoke方法,很多异常的抛出多会定位到invoke方法:

java.lang.NullPointerException at ...... at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) invoke执行过程

invoke方法用来在运行时动态地调用某个实例的方法,实现如下:

@CallSensitive public Object invoke(Object obj, Object ... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { Class<?> caller = Refelection.getCallerClass(); checkAccess(caller, clazz, obj, modifiers); } } MethodAccessor ma = methodAccessor; if (ma == null) { ma = acquireMethodAccessor(); } return ma.invoke(obj, args); } 权限检查

AccessibleObject类是Field,MethodConstructor对象的基类:

提供将反射的对象标记为在使用时取消默认Java语言访问控制检查的能力

invoke方法会首先检查AccessibleObjectoverride属性的值:

override默认值为false:

表示需要权限调用规则,调用方法时需要检查权限

也可以使用setAccessible() 设置为true

override如果值为true:

表示忽略权限规则,调用方法时无需检查权限

也就是说,可以调用任意private方法,违反了封装

如果override属性为默认值false,则进行进一步的权限检查:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zydsyj.html