获取Class类
得到Class类有三种方法:
.class,在加载了某个类的情况下,直接拿它的属性即可,例如:Runtime.class。
obj.getClass()。如果存在某个类的实例obj,那么可以通过getClass()方法得到这个类对应的Class。
Class.forName,也是最常用的。知道了那个类的完整名字后(包括包名),作为参数即可:Class clazz = Class.forName("java.lang.Runtime");
获取成员变量Field
Class类有这些获取属性的方法:
//返回 字段对象,该对象反映此 类对象表示的类或接口的指定声明字段。
getDeclaredField(String name)
//返回 字段对象的数组, 字段对象反映由此 类对象表示的类或接口声明的所有字段。
getDeclaredFields()
//返回 字段对象,该对象反映此 类对象表示的类或接口的指定公共成员字段。
getField(String name)
//返回一个包含 字段对象的数组, 字段对象反映此 类对象所表示的类或接口的所有可访问公共字段。
getFields()
注意:上面两个可以获取的是所有的成员变量,下面的两个得到的只有public的成员变量。第一第三个可以传入一个名字(字符串)来得到指定的成员变量,而第二第四个只能得到一个数组,没法得到指定的。
还有一个需要注意的点,就是前两个虽然不受到public的限制,但是它不能得到父类的成员变量。后两个虽然只能得到public成员变量,但是可以得到父类的public成员变量。
举个例子
Class clazz = Class.forName("com.a.Student");
Field code = clazz.getDeclaredField("code");
System.out.println(code.getName());
//我们可以用set方法去设置类
code.set(1,1);
获取方法Method
Class类有这些获取Method的方法:
//返回 方法对象,该对象反映此 类对象表示的类或接口的指定声明方法。
getDeclaredMethod(String name, 类<?>... parameterTypes);
//返回一个包含 方法对象的数组, 方法对象反映此 类对象表示的类或接口的所有已声明方法,包括public,protected,default(package)访问和私有方法,但不包括继承的方法。
getDeclaredMethods();
//返回 方法对象,该对象反映此 类对象表示的类或接口的指定公共成员方法。
getMethod(String name, 类<?>... parameterTypes);
//返回一个包含 方法对象的数组, 方法对象反映此 类对象所表示的类或接口的所有公共方法,包括由类或接口声明的那些以及从超类和超接口继承的那些。
getMethods();
Class clazz = Class.forName("java.lang.Runtime");
clazz.getMethod("exec", String.class).invoke(clazz.getMethod("getRuntime").invoke(clazz), "calc.exe");
获取构造函数
//返回一个 构造器对象,该对象反映此 类对象所表示的类或接口的指定构造函数。
getDeclaredConstructor(类<?>... parameterTypes)
//返回 构造器对象的数组, 构造器对象反映由此 类对象表示的类声明的所有构造函数。
getDeclaredConstructors()
//返回一个 构造器对象,该对象反映此 类对象所表示的类的指定公共构造函数。
getConstructor(类<?>... parameterTypes)
//返回一个包含 构造器对象的数组, 构造器对象反映了此 类对象所表示的类的所有公共构造函数。
getConstructors()
Class clazz = Class.forName("com.javalearn.summer.Employee");
Constructor cons = clazz.getDeclaredConstructor(String.class,double.class);
实例化类
直接用class.newInstance() 的作用就是调用这个类的无参构造函数
Class clazz = Class.forName("com.javalearn.summer.Employee");
Object o = clazz.newInstance();
System.out.println(o);
但是这样实例化类,相当于调用类的无参构造器,当需要调用非无参构造器来实例化类的时候,就需要用到之前得到的Constructor了:
Class clazz = Class.forName("com.javalearn.summer.Employee");
Constructor cons = clazz.getDeclaredConstructor(String.class,double.class);
Object f = cons.newInstance("feng", 123);
调用方法
正常执行方法是 [1].method([2], [3], [4]…) ,其实在反射里就是method.invoke([1], [2], [3], [4]…)
那么我们调用命令执行的方法步骤拆分开来就是
Class clazz = Class.forName("java.lang.Runtime");
Method execMethod = clazz.getMethod("exec", String.class);
Method getRuntimeMethod = clazz.getMethod("getRuntime");
Object runtime = getRuntimeMethod.invoke(clazz);
execMethod.invoke(runtime, "calc.exe");
或者我们也可以直接用 getDeclaredConstructor 来获取这个私有的构造方法来实例化对象,进而执行命令
//这里使用了一个方法 setAccessible ,这个是必须的。我们在获取到一个私有方法后,必须用
//setAccessible 修改它的作用域,否则仍然不能调用
Class clazz = Class.forName("java.lang.Runtime");
Constructor m = clazz.getDeclaredConstructor();
m.setAccessible(true);
clazz.getMethod("exec", String.class).invoke(m.newInstance(), "calc.exe");