Java反射机制

Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。

而在一个对象或者方法的作用域是default或private时,我们是无法进行直接的调用的,这时候就需要用到java的反射机制了。

而java的反射机制总共有4个调用方式,分别是Class.forName方法、new调用、.class调用和getClass方法。然而通过实测只有forName能调用ProcessImpl类。

//第一种方法,使用class.forName进行调用
Class<?> clazz1 = Class.forName("java.lang.ProcessBuilder");
//第二种方法,new一个要调用的类的对象
ProcessBuilder clazz2 = new ProcessBuilder();
//第三种方法,需要调用的类名加上.Class
Class<ProcessBuilder> clazz3 = ProcessBuilder.class;
//第四种方法,定义字符串调用需要的类,使用getClass获取该类
String str = "java.lang.ProcessBuilder";
Class clazz = str.getClass();

 

在上一篇文章中,由于ProcessImpl无法直接调用,所以使用了java的反射机制来调用。而调用还需要一些步骤。因为forName只是获取了这个类,后面是通过Method类来获取需调用的方法。getDeclaredMethod是从当前类所有声明的方法中获取方法,不包括父类声明的方法,而getMethod函数是从public方法中获取方法,显然不适用。最后通过invoke调用start方法。

public class ProcesslmplTest {
public static void main(String []args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException{
Class clazz = Class.forName("java.lang.ProcessImpl"); // 获取ProcessImpl的Class对象
Method method = clazz.getDeclaredMethod("start", String[].class, Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class); // 获取start方法对象
method.setAccessible(true); // 设置方法允许在当前代码使用
Process p = (Process) method.invoke(null, new String[]{"cmd.exe","/c","calc.exe"}, null, ".", null, true); // 调用start方法
System.out.println(p);
}
}

Java反射相关操作

Java反射时使用了forName来获取类,我们可以通过这个类来获取类的方法等:

  • 获取成员方法Method
  • 获取成员变量Field
  • 获取构造函数Constructor

获取成员方法信息

public Method getDeclaredMethod(String name, Class<?>... parameterTypes) // 得到该类所有的方法,不包括父类的
public Method getMethod(String name, Class<?>... parameterTypes) // 得到该类所有的public方法,包括父类的

即前面使用到的getDeclaredMethod方法。还可以通过Method[]来循环查询类的所有方法。

获取成员变量信息

public Field getDeclaredField(String name) // 获得该类自身声明的所有变量,不包括其父类的变量
public Field getField(String name) // 获得该类自所有的public成员变量,包括其父类变量

获取构造函数

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) //  获得该类所有的构造器,不包括其父类的构造器
public Constructor<T> getConstructor(Class<?>... parameterTypes) // 获得该类所以public构造器,包括父类

了解了这些也算是对java反射机制有了初步的认识了。