概述
最近在读公司框架源码的时候,多处用到了反射,现在写一篇文章来复习一下反射这部分的知识。反射的核心是JVM在运行时才动态加载类、调用方法、访问属性。如果你需要用到某方法,但是那个方法是私有的,这个时候你就可以通过反射去执行这个私有方法,并且获取私有变量。
常用方法
- 首先需要获取一个类的Class对象
获取类的Class对象主要有三种方式:
Person person = new Person();
Class personClass1= person.getClass();
Class personClass2 = Person.class;
(最常用)
Class personClass3 = Class.forName("com.demo.Person");
- 获取构造器
用getDeclaredConstructors()返回类的所有构造方法
getDeclaredConstructor()获取特定参数类型的构造方法 - 获取方法
getDeclaredMethod() - 获取成员变量
getDeclaredField() - 创建实例
newInstance() - 调用方法
invoke(),参数一个是类的实例,一个是方法参数。
如果方法、变量是private的 先要setAccessible(true) - 其他
getModifiers()
返回此类或接口以整数编码的Java语言修饰符:
PUBLIC: 1
PRIVATE: 2
PROTECTED: 4
STATIC: 8
FINAL: 16
SYNCHRONIZED: 32
VOLATILE: 64
TRANSIENT: 128
NATIVE: 256
INTERFACE: 512
ABSTRACT: 1024
STRICT: 2048
instanceof关键字:判断左边的对象是否是它右边的类的实例。
案例
写一个简单的例子,便于理解:
首先定义一个简单的测试类
package demo;
public class Person {
private Integer id;
private String name;
private Integer age;
private Person() {
System.out.println("无参构造被调用...");
}
private Person(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
System.out.println("构造方法被调用...");
}
private void hello(String s){
System.out.println(s);
}
public void test(){
System.out.println("test....");
}
}
package demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestReflex {
/**
* 获取无参构造
*/
private static Constructor<?> getConstructor(Class<?> aClass) throws NoSuchMethodException {
return aClass.getDeclaredConstructor();
}
/**
* 获取另一个构造函数
*/
private static Constructor<?> getConstructorWithPar(Class<?> aClass) throws NoSuchMethodException {
Class[] p = {Integer.class,String.class,Integer.class};
return aClass.getDeclaredConstructor(p);
}
/**
* 获取类的方法
*/
private static Method getMethod(Class<?> aClass) throws NoSuchMethodException {
return aClass.getDeclaredMethod("hello", String.class);
}
public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
Class<?> aClass = Class.forName("demo.Person");
Constructor<?> constructor = getConstructor(aClass);
constructor.setAccessible(true);
System.out.println(constructor.getModifiers());
Person person = (Person) constructor.newInstance();
person.test();
System.out.println("------------------");
Constructor<?> constructorWithPar = getConstructorWithPar(aClass);
constructorWithPar.setAccessible(true);
Object obj = constructorWithPar.newInstance(1, "张三", 18);
Method method = getMethod(aClass);
method.setAccessible(true);
String s = "hello";
method.invoke(obj,s);
System.out.println("------------------");
Field name = aClass.getDeclaredField("name");
name.setAccessible(true);
System.out.println(name.get(obj).toString());
name.set(obj,"高");
System.out.println(name.get(obj).toString());
}
}
输出结果: