反射
Java反射机制是在运行状态时,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。
获取类
JVM为每个加载的class创建了对应的Class实例,并在实例中保存了该class的所有信息;因此,如果获取了某个Class实例,我们就可以通过这个Class实例获取到该实例对应的class的所有信息。
常用的由以下几种方式获取类:
1 2 3 4 5 6 7 8 9 10 11 12
   |  Class clazz = String.class;
 
  String s = ""; Class clazz = s.getClass();
 
  Class clazz = Class.forName("java.lang.String");
 
  Class<?> clazz = this.getClass().getClassLoader().loadClass("com.spring.sec.ClassLoader.reflectTest");
 
  | 
 
获取类之后就可以对类进行访问修改等操作,值得注意的是,上述四种方法所获取的Class实例是同一个。
获取属性
1 2 3 4 5 6 7 8 9 10 11
   | Class<?> clazz = Class.forName("com.spring.sec.reflectTest");
   Field[] fields = clazz.getFields();
   Field field = clazz.getField("property");
     Field[] declaredFields = clazz.getDeclaredFields();
   Field declaredField = clazz.getDeclaredField("property");
 
 
  | 
 
对于获取到的属性,我们想要在具体的实例中获取需要使用get()方法,修改需要使用set()方法.
1 2 3 4
   | Object o = field.get(clazz.newInstance());
  field.set(clazz.newInstance(),"edited_property");
 
 
  | 
 
另外对于private,protected修饰的属性需要先设置可编辑才能修改:
1
   | privateField.setAccessible(true);
 
  | 
 
获取方法
getMehtod() 其原型是
1 2
   | public reflect.Method getMethod(@NonNls @NotNull String name,                							 Class<?>... parameterTypes)
 
  | 
 
一些例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | Class<?> clazz = Class.forName("com.spring.sec.reflectTest");
  Method[] methods = clazz.getMethods();
  Method method = clazz.getMethod("name");
 
  Method[] methods = clazz.getDeclaredMethods();
  Method method = clazz.getDeclaredMethod("name");
 
 
  Method method = clazz.getDeclaredMethod("name",String.class); 
 
 
 
  | 
 
调用: invoke()
获取方法后执行需要调用invoke(),其原型是
1
   | public Object invoke(Object obj, Object... args)
 
  | 
 
obj是实例,args是参数例如
1 2 3 4
   | method.invoke(clazz,new String("springtime"));
 
  method.invoke(clazz);
 
  | 
 
注意:若调用的方法为静态方法,则第一个参数必须是null
1 2 3 4 5
   |  Method m = Integer.class.getMethod("parseInt", String.class);
  Integer n = (Integer) m.invoke(null, "23333"); System.out.println(n);
 
  | 
 
获取构造器
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | Constructor<?> constructor = clazz.getConstructor();
  Constructor<?> constructor = clazz.getDeclaredConstructor()
 
  Constructor<?> constructor = clazz.getConstructor(...parameterTypes)
  Constructor<?> constructor = clazz.getDeclaredConstructor(...parameterTypes)
 
  Constructor<?>[] constructors = clazz.getConstructors();
  Constructor<?>[] Constructors = clazz.getDeclaredConstructors();
 
 
  | 
 
实例化: newInstance()
注意:java.lang.Class.newInstance()与java.lang.refelct.Constructor.newInstance()不同,前者是无参构造方法调用,而后者是构造方法重载调用。
1 2
   | Object o = clazz.newInstance(); Object o = constructor.newInstance(@Nullable Object... initargs);
 
  | 
 
修改final关键字修饰的属性
被final关键字修饰的属性我们无法使用set()方法修改,需要借助类中的modifiers。
1 2 3 4 5 6 7 8 9 10 11
   |  Field modifiers = field.getClass().getDeclaredField("modifiers");
 
  modifiers.setAccessible(true);
 
  modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
 
  field.set(obj, "edited_value");
 
  | 
 
反射命令执行
1
   | Class.forName("java.lang.Runtime").getMethod("exec",String.class).invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime")),"calc.exe");
 
  | 
 
高版本JDK下的反射
@TODO