从类中获取一个方法后,可以使用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类的set和get方法都是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,Method和Constructor对象的基类:
提供将反射的对象标记为在使用时取消默认Java语言访问控制检查的能力
invoke方法会首先检查AccessibleObject的override属性的值:
override默认值为false:
表示需要权限调用规则,调用方法时需要检查权限
也可以使用setAccessible() 设置为true
override如果值为true:
表示忽略权限规则,调用方法时无需检查权限
也就是说,可以调用任意private方法,违反了封装
如果override属性为默认值false,则进行进一步的权限检查: