Java反射
概念
Java反射指在程序执行时:
- 对于类
能够获得类的所有属性和方法
- 对于对象
能够通过对象调用它的任意一个方法和属性(包括私有的方法和属性)
这种动态获取并调用类的方法的机制称为Java反射
获取一个类
通过类名
包括查看类的静态变量以及通过完整类名获取
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
// 通过查看静态变量
Class cls = String.class;
System.out.println(cls);
// 通过一个类的完整类名获取
Class cls2 = Class.forName("java.lang.String");
System.out.println(cls2);
}
}
通过对象
通过对象的getClass方法
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
String s = "test";
Class cls = s.getClass();
System.out.println(cls);
}
}
访问类的字段
在Java中类字段对应的类型为Field
getFields()
获得某个类的所有public字段,包括父类中的public字段
import java.lang.reflect.Field;
class tester {
static public int id = 2;
public int getMoney() { // getter方法
return money;
}
private int money;
protected int age;
public String name;
public String school;
}
public class Main {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
tester test = new tester();
Class cls = test.getClass();
Field id = cls.getField("id");
System.out.println(id); // public static int tester.id
System.out.println(id.get(cls.newInstance())); // 需要再创建实例 然后才能获取字段值
}
}
getDeclaredFields()
tester test2 = new tester();
Field money = cls.getDeclaredField("money");
money.setAccessible(true); // 赋予权限
money.set(test2, 666);
System.out.println(test2.getMoney());
访问类的方法
有如下四种方法
- getMethod
获取某个public
的Method
(包括父类)
public Method getMethod(String name, Class<?>... parameterTypes)
- getDeclaredMethod
获取当前类的某个Method
(不包括父类)
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
- getMethods
获取所有public
的Method
(包括父类)
- getDeclaredMethods
获取当前类的所有Method
(不包括父类)
import java.lang.reflect.Method;
class tester {
static public int id = 2;
public int getMoney() {
return money;
}
private int money;
protected int age;
public String name;
public String school;
public void test1(){
System.out.println("This is my test 1");
}
static public void test2(){
System.out.println("This is my test 2");
}
}
public class Main {
public static void main(String[] args) throws Exception {
tester test = new tester();
Class testClass = test.getClass();
Method m = testClass.getMethod("test1");
m.invoke(test, null);
Method m2 = testClass.getDeclaredMethod("test2");
m2.invoke(test,null);
}
}
获取构造方法
- getConstructor
获取某个public
的Constructor
public Constructor<T> getConstructor(Class<?>... parameterTypes)
- getDeclaredConstructor
获取某个Constructor
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
-
getConstructors:获取所有
public
的Constructor
; -
getDeclaredConstructors:获取所有
public
的Constructor
;
import java.lang.reflect.Constructor;
class tester {
public tester(){
System.out.println("无参构造方法");
}
public tester(String name){
this.name = name;
System.out.println("有参构造方法");
}
static public int id = 2;
public int getMoney() {
return money;
}
private int money;
protected int age;
public String name;
public String school;
public void test1(){
System.out.println("This is my test 1");
}
static public void test2(){
System.out.println("This is my test 2");
}
}
public class Main {
public static void main(String[] args) throws Exception {
Class testClass = tester.class;
// 有参的得加入参数的类型
Constructor constructor = testClass.getConstructor(String.class);
Object obj = constructor.newInstance("123");
Constructor constructor1 = testClass.getConstructor();
Object obj1 = constructor1.newInstance();
}
}
通过反射执行命令
- 未使用反射
Runtime.getRuntime().exec("calc");
- 反射
Class cls = Class.forName("java.lang.Runtime");
Method m = cls.getMethod("exec", String.class);
Method m2 = cls.getMethod("getRuntime");
Object obj = m2.invoke(cls);
m.invoke(obj,"calc");
- 一句话版本
Class.forName("java.lang.Runtime").getMethod("exec", String.class).invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime")),"calc" );
总结
- 获取类的⽅法: forName,getClass
- 实例化类对象的⽅法: newInstance
- 获取函数的⽅法: getMethod
- 执行函数的⽅法: invoke