Reflect
Java反射机制时在运行状态中,对于任意一个类,都能知道这个类所有的属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为Java语言的反射机制。(就是通过class文件对象,使用该文件中的成员变量、构造方法、成员方法)
获取class文件对象(Class)
- Object类中的getClass()方法
- 数据类型的静态属性class
- Class.forName("类路径")
public class Student {
private String name;
Integer age;
public String addr;
public Student() {
}
public Student(String name, Integer age, String addr) {
this.name = name;
this.age = age;
this.addr = addr;
}
private Student(String addr) {
this.addr = addr;
}
public String method(String s) {
return String.format("method_%s", s);
}
void show() {
System.out.println("student show");
}
private void test() {
System.out.println("student test ");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", addr='" + addr + '\'' +
'}';
}
}
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
// Object类中的getClass()方法
Student student = new Student();
Class<? extends Student> aClass = student.getClass();
// 数据类型的静态属性class
Class<Student> bClass = Student.class;
// Class.forName("类路径")
Class<?> cClass = Class.forName("com.net.reflect.Student");
// 三种方式获取的是同一个class文件对象
// true
System.out.println(aClass == bClass);
// true
System.out.println(bClass == cClass);
}
}
获取构造方法并使用
public class ReflectDemo2 {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
// 获取字节码文件对象
Class<Student> studentClass = Student.class;
// 获取所有公共构造方法
Constructor<?>[] constructors = studentClass.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
// 获取所有构造方法
Constructor<?>[] declaredConstructors = studentClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
// 获取指定构造方法并使用
Constructor<Student> declaredConstructor = studentClass.getDeclaredConstructor(String.class, Integer.class, String.class);
System.out.println(declaredConstructor);
// 创建实例
Student student = declaredConstructor.newInstance("zhansan", 11, "aaa");
System.out.println(student);
// 获取私有方法并使用
Constructor<Student> con = studentClass.getDeclaredConstructor(String.class);
// 设置访问权限
con.setAccessible(true);
// 创建实例
Student student1 = con.newInstance("bbb");
System.out.println(student1);
}
}
获取成员变量并使用
public class ReflectField {
public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
// 获取字节码文件对象
Class<Student> studentClass = Student.class;
// 获取所有公开的成员变量
// public java.lang.String com.net.mybatisplus.reflect.Student.addr
Field[] fields = studentClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
// 获取所有成员变量
// private java.lang.String com.net.mybatisplus.reflect.Student.name
// java.lang.Integer com.net.mybatisplus.reflect.Student.age
// public java.lang.String com.net.mybatisplus.reflect.Student.addr
Field[] declaredFields = studentClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
// 获取单个公开成员变量并对其赋值
Constructor<Student> constructor = studentClass.getConstructor();
Student student = constructor.newInstance();
Field addr = studentClass.getField("addr");
addr.set(student, "ccc");
// Student{name='null', age=null, addr='ccc'}
System.out.println(student);
// 获取单个私有成员变量并对其赋值
Field name = studentClass.getDeclaredField("name");
name.setAccessible(true);
name.set(student, "zhangsan");
// Student{name='zhangsan', age=null, addr='ccc'}
System.out.println(student);
}
}
获取成员方法并使用
public class ReflectMethod {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
// 获取字节码文件对象
Class<Student> studentClass = Student.class;
// 获取所有公开方法(包括父类)
Method[] methods = studentClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("-----------------");
// 获取所有方法(不包括父类)
Method[] declaredMethods = studentClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("-----------------");
// 获取单个公开方法并使用
Constructor<Student> constructor = studentClass.getConstructor();
Student student = constructor.newInstance();
Method method = studentClass.getMethod("method", String.class);
Object stuMethod = method.invoke(student, "stuMethod");
System.out.println(stuMethod);
System.out.println("-----------------");
// 获取单个私有方法并使用
Method test = studentClass.getDeclaredMethod("test");
test.setAccessible(true);
test.invoke(student);
}
}
工具类
public class ReflectTool {
// 赋值对象的任意属性
public static void setProperty(Object obj, String propertyName, Object value)
throws NoSuchFieldException, IllegalAccessException {
// 获取字节码文件对象
Class<?> aClass = obj.getClass();
// 获取成员变量
Field declaredField = aClass.getDeclaredField(propertyName);
// 取消访问检查
declaredField.setAccessible(true);
// 赋值
declaredField.set(obj, value);
}
}
反射越过泛型检查
public class ListReflect {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
List<Integer> list = Lists.newArrayList();
Class<? extends List> aClass = list.getClass();
Method add = aClass.getDeclaredMethod("add", Object.class);
add.setAccessible(true);
add.invoke(list, "list1");
add.invoke(list, 11);
add.invoke(list, true);
System.out.println(list);
}
}