反射
- 什么是反射
反射是一种动态获取和操作类信息的机制,它使得我们可以在运行时动态地加载类、调用方法、访问属性等。它在一些特定的场景下非常有用,比如框架开发、配置文件解析、动态代理等。
import java.lang.reflect.Constructor;//类的构造方法,我们可以使用它获取和操作类的构造方法。
import java.lang.reflect.Field;//类的字段,我们可以使用它获取和操作类的字段。
import java.lang.reflect.Method;//类的方法,我们可以使用它获取和操作类的方法。
import java.lang.reflect.Parameter;//方法或构造方法的参数,我们可以使用它获取参数的类型和名称等信息。
- 使用反射获取和打印User类的各种信息,包括类名、父类、实现的接口、包信息和字段信息。
package com.wz.reflect01;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
basic();
}
public static void basic(){
//获取class对象
Class<User> clazz = User.class;
//获取类的全限定名
String name = clazz.getName();
System.out.println("类的全限定名:"+name);
//获取普通类名
String simpleName = clazz.getSimpleName();
System.out.println("类名:"+simpleName);
//获取父类
Class<? super User> superclass = clazz.getSuperclass();
System.out.println("父类的全限定名:"+superclass.getName());
System.out.println("父类的名字:"+superclass.getSimpleName());
//返回一个数组,包含了该类所实现的接口的Class对象。
Class<?>[] interfaces = clazz.getInterfaces();
if (interfaces.length>0){
System.out.println("类实现的接口:"+ Arrays.toString(interfaces));
}
//获取类的包信息
Package clazzPackage = clazz.getPackage();
String packageName = clazzPackage.getName();
System.out.println("类所在的包:"+packageName);
//获取类中的字段(public 修饰的字段)
// Field[] fields = clazz.getFields();
Field[] fields = clazz.getDeclaredFields();
for (Field field:fields){
Class<?> type = field.getType();//获取字段类型
String fieldName = field.getName();//获取字段名
System.out.println("字段名"+fieldName+",字段类型"+type.getName());
}
//获取类中的方法(public修饰的方法)
// Method[] methods = clazz.getMethods();
Method[] methods = clazz.getDeclaredMethods();
for (Method method:methods){
String methodName = method.getName();//获取方法的名字
Class<?> returnType = method.getReturnType();//获取方法的返回值类型
Parameter[] parameters = method.getParameters();//获取方法的参数列表
StringBuilder builder = new StringBuilder();
if (parameters !=null){
for (Parameter p:parameters){
Class<?> parameterType = p.getType(); //参数类型
String parameterName = p.getName(); //参数的名称
builder.append(parameterType).append(" ").append(parameterName).append(",");
}
if (builder.length()>0){
builder.deleteCharAt(builder.length()-1);
}
System.out.println("方法:"+returnType+" "+methodName+"("+ builder.toString() + ")");
}
}
//获取类中的公开的构造方法
// Constructor<?>[] constructors = clazz.getConstructors();
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
for (Constructor<?> constructor: constructors){
String constructorName = constructor.getName();
Parameter[] parameters = constructor.getParameters();
StringBuilder builder = new StringBuilder();
if(parameters != null){
for(Parameter p: parameters){
Class<?> parameterType = p.getType(); //参数类型
String parameterName = p.getName(); //参数的名称
builder.append(parameterType).append(" ").append(parameterName).append(",");
}
if(builder.length() > 0)
builder.deleteCharAt(builder.length()-1);
}
System.out.println("构造方法:" + constructorName + "(" + builder.toString() + ")");
}
}
}
结果:
//修改访问权限
public void setAccessible(boolean flag) throws SecurityException;
- 案例: 如何使用Java反射来动态调用方法
public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
package com.wz.reflect01;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectTest {
public static void main(String[] args) throws Exception {
User user = new User();
user.setUsername("admin");
user.setPassword("123456");
System.out.println(user);
//使用Java反射获取User类的Class对象
Class<User> clazz = User.class;
//使用反射创建User类的实例
User u = clazz.newInstance();
//通过方法名和参数列表的类型到细字节码中去找到匹配的方法
Method method = clazz.getMethod("setUsername", String.class);
method.invoke(u,"admin");
method = clazz.getMethod("setPassword", String.class);
method.invoke(u,"123456");
System.out.println(u);
User u2 = clazz.newInstance();
//获取类中定义的字段
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// String fieldName = field.getName();
// username => setUsername = set + U + sername
// String methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
// Class<?> fieldType = field.getType();
// Method m = clazz.getMethod(methodName, fieldType);
// m.invoke(u2, "test");
//私有的字段不能够直接访问,那么我们可以先拿到访问的权限,即设置这个字段可访问
field.setAccessible(true);
//直接为字段赋值
field.set(u2, "test");
}
System.out.println(u2);
}
}
结果: