目录
介绍
反射机制是什么
Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。
Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。
我们编译时知道类或对象的具体信息,此时直接对类和对象进行操作即可,无需使用反射(reflection)
如果编译不知道类或对象的具体信息,此时应该如何做呢?这时就要用到 反射 来实现。比如类的名称放在XML文件中,属性和属性值放在XML文件中,需要在运行时读取XML文件,动态获取类的信息
编译时根本无法知道该对象或类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息
比如:log4j,Servlet、SSM框架技术都用到了反射机制
获取字节码的三种方式
1.Class.forName(“完整类名带包名”)
2.对象.getClass()
3.任何类型.class
Class类方法
方法名 | 备注 |
---|---|
public T newInstance() | 创建对象 |
public String getName() | 返回完整类名带包名 |
public String getSimpleName() | 返回类名 |
public Field[] getFields() | 返回类中public修饰的属性 |
public Field[] getDeclaredFields() | 返回类中所有的属性 |
public Field getDeclaredField(String name) | 根据属性名name获取指定的属性 |
public native int getModifiers() | 获取属性的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】 |
public Method[] getDeclaredMethods() | 返回类中所有的实例方法 |
public Method getDeclaredMethod(String name, Class<?>… parameterTypes) | 根据方法名name和方法形参获取指定方法 |
public Constructor<?>[] getDeclaredConstructors() | 返回类中所有的构造方法 |
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) | 返回Class对象的无参构造方法 |
public Constructor getDeclaredConstructor(Class<?>… parameterTypes) | 根据方法形参获取指定的构造方法 |
public native Class<? super T> getSuperclass() | 返回调用类的父类 |
public Class<?>[] getInterfaces() | 返回调用类实现的接口集合 |
反射/反编译一个类的属性(Filed)
Field类方法
方法名 | 介绍 |
---|---|
public String getName() | 返回属性名 |
public int getModifiers() | 获取属性的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】 |
public Class<?> getType() | 以Class类型,返回属性类型【一般配合Class类的getSimpleName()方法使用】 |
public void set(Object obj, Object value) | 设置属性值 |
public Object get(Object obj) | 读取属性值 |
目录结构
User类
public class User {
private String name;
private String password;
private Integer age;
public int no;
public String phone;
public boolean login(String name,String password){
return "zhangsan".equals(name) && "123".equals(password);
}
/**
有参构造、无参构造、get方法、set方法、toString方法
**/
}
通过反射机制对一个对象的属性赋值
对于public修饰的属性
/**
给属性赋值三要素
eg. 给use对象的phone属性赋值111111111111
要素1:对象 user
要素2:phone 属性
要素3:111111111111 值
读属性值两个要素
eg. 获取user对象的phone属性的值
要素1:对象 user
要素2:phone属性
**/
public static void reflectFiled() throws Exception {
Class<?> userClass = Class.forName("entity.User");
Object user = userClass.newInstance();
Field phone = userClass.getDeclaredField("phone");
//对象的属性.set(对象,对象的值)
phone.set(user,"111111111111");
//对象的属性.get(对象)
System.out.println(phone. Get(user));
}
对于非public修饰的属性
public static void reflectFiled() throws Exception {
Class<?> userClass = Class.forName("entity.User");
Object user = userClass.newInstance();
Field name = userClass.getDeclaredField("name");
//打破封装,让set方法可以访问非公有属性
name.setAccessible(true);
name.set(user,"张三");
System.out.println(name. Get(user));
}
结果:
反射/反编译一个类的方法(method)
Method类方法
方法名 | 备注 |
---|---|
public String getName() | 返回方法名 |
public int getModifiers() | 获取方法的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】 |
public Class<?> getReturnType() | 以Class类型,返回方法类型【一般配合Class类的getSimpleName()方法使用】 |
public Class<?>[] getParameterTypes() | 返回方法的修饰符列表(一个方法的参数可能会有多个。)【结果集一般配合Class类的getSimpleName()方法使用】 |
public Object invoke(Object obj, Object… args) | 调用方法 |
通过反射机制调用一个对象的方法
public static void reflectMethod() throws Exception {
Class<?> userClass = Class.forName("entity.User");
Object user = userClass.newInstance();
//getDeclaredMethod(方法名,形参类型,形参类型....)
Method login = userClass.getDeclaredMethod("login", String.class,String.class);
//invoke(对象,形参,形参)
//如果是非公有方法
//login.setAccessible(true);
Object invoke = login.invoke(user, "张三", "123");
System.out.println(invoke);
}
结果:
反射/反编译一个类的构造方法
Constructor类方法
方法名 | 备注 |
---|---|
public String getName() | 返回构造方法名 |
public int getModifiers() | 获取构造方法的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】 |
public Class<?>[] getParameterTypes() | 返回构造方法的修饰符列表(一个方法的参数可能会有多个。)【结果集一般配合Class类的getSimpleName()方法使用】 |
public T newInstance(Object … initargs) | 创建对象【参数为创建对象的数据】 |
通过反射机制调用一个对象的构造方法
public static void reflectConstructor() throws Exception {
Class<?> userClass = Class.forName("entity.User");
//获取这个对象的有参构造器
Constructor<?> c1 = userClass.getDeclaredConstructor(String.class, String.class, Integer.class, int.class, String.class);
//调用构造方法创建对象
Object instance1 = c1.newInstance("张三", "123", 19, 111, "121212121");
System.out.println(instance1);
//获取这个对象的有参构造器
Constructor<?> c2 = userClass.getDeclaredConstructor();
//调用无参方法创建对象
Object instance2 = c2.newInstance();
System.out.println(instance2);
}
结果:
获取一个类的父类以及实现的接口
准备
public class T extends T4 implements T1,T2,T3{
}
public interface T1 {
}
public interface T1 {
}
public interface T3 {
}
public class T4 {
}
代码实现:
public static void reflectSuperAndInterface() throws Exception {
Class<?> tClass = Class.forName("entity.T");
//获取 T 的 父类
Class<?> superclass = tClass.getSuperclass();
System.out.println("T的父类:"+superclass.getName());
//获取 T 类实现的所有接口
Class<?>[] interfaces = tClass.getInterfaces();
System.out.println("T实现的接口如下:");
for (Class<?> i : interfaces) {
System.out.println(i.getName());
}
}
结果: