Class (反射的入口)、Method (成员方法)、Field (成员变量)java
java反射经常使用的一些实例ide
package cn.com; import java.lang.reflect.Method; /** * Copyright (C), 2018-2019 * * @Description: TODO * @Author: zhou * @Create: 2019/10/10 16:36 * @Version 1.0.0 */ public class MethodInvoke { public static void main(String[] args) throws Exception { Class implClass = Class.forName("cn.com.Animal"); Object instance = implClass.newInstance(); // 实例 System.out.println("instance:" + instance); Method method = instance.getClass().getMethod("print"); method.invoke(instance); Method method1 = implClass.getDeclaredMethod("print"); method1.invoke(instance);
// 访问是有方法 printS
Method privteMethod = implClass.getDeclaredMethod("printS");
privteMethod.setAccessible(true); //设置或取消访问检查,以达到访问私有对象的目的。
privteMethod.invoke(instance);
Method animalMethod = Animal.class.getDeclaredMethod("print"); Method catMethod = Cat.class.getDeclaredMethod("print"); Animal animal = new Animal(); Cat cat = new Cat(); animalMethod.invoke(cat); animalMethod.invoke(animal); System.out.println("====="); catMethod.invoke(cat); catMethod.invoke(animal); } } class Animal { public void print() { System.out.println("Animal.print()"); }
private void printS(){
System.out.println("Animal.privateFunction");
}
}
class Cat extends Animal { @Override public void print() { System.out.println("Cat.print()"); } }
获取反射的方法有:ui
第一种:
Class animal =Animal.class;
第二种:
Class animal = Class.forName("cn.com.Animal"); // Animal类的全路径
获取到 Class 以后,即可以获取有参方法
Method method = animal.getDeclaredMethod(String name, Class<?>... parameterTypes);
Method method = animal.getMethod(String name, Class<?>... parameterTypes);
其中: name 为方法名,paramterTypers方法的参数类型
能够经过 Object instance = animal.newInstance(); 将类实例化
最后经过
method.invoke(instance, parameValue);
instance为类是实例化,paramValue为方法参数(根据实际状况传入)
java反射可饶过不能访问私有方法的限制,须要添加
setAccessible(true); //设置或取消访问检查,以达到访问私有对象的目的。
接下来,咱们来看看invoke()方法的实现过程。
@CallerSensitive public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { Class<?> caller = getCallerClass(); checkAccess(caller, clazz, obj, modifiers); } } MethodAccessor ma = methodAccessor; // read volatile if (ma == null) { ma = acquireMethodAccessor(); } return ma.invoke(obj, args); }
invoke()方法中主要分为两部分:访问控制检查和调用MethodAccessor.invoke()实现方法执行。this
访问控制检测分有3步:spa
一、检查override.net
二、快速检查,判断该方法的修饰符modifiers是否为public3d
三、详细检查,经过方法的(protected/private/package)修饰符或方法的声明类(例如子类能够访问父类的protected方法)与调用者caller之间的关系,判断caller是否有权限访问该方法。code
override属性是Method的父类AccessibleObject中声明的变量,使得程序能够控制是否跳过访问权限的检查。另外,Method的实例对象中,override属性的初始值设置为false。
public void setAccessible(boolean flag) throws SecurityException { SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkPermission(ACCESS_PERMISSION); setAccessible0(this, flag); } /* Check that you aren't exposing java.lang.Class.<init>. */ private static void setAccessible0(AccessibleObject obj, boolean flag) throws SecurityException { if (obj instanceof Constructor && flag == true) { Constructor<?> c = (Constructor<?>)obj; if (c.getDeclaringClass() == Class.class) { throw new SecurityException("Can not make a java.lang.Class" + " constructor accessible"); } } obj.override = flag; }
部分代码来源:https://blog.csdn.net/wenyuan65/article/details/81145900