概述
包名: java.lang.reflect.*
运行过程中, 通过反射机制操作字节码文件
反射是框架的灵魂
内存方法区对于每个class, 只存在唯一的Class对象, 如下图Student.class
反射主要涉及的相关类
包类 | 含义 |
java.lang.Class | 类 |
java.lang.reflect.Constructor | 类中的构造方法 |
java.lang.reflect.Field | 类中的成员变量 |
java.lang.reflect.Method | 类中的成员方法 |
Class类
private static class ReflectionData<T> {
volatile Field[] declaredFields;
volatile Field[] publicFields;
volatile Method[] declaredMethods;
volatile Method[] publicMethods;
volatile Constructor<T>[] declaredConstructors;
volatile Constructor<T>[] publicConstructors;
// Intermediate results for getFields and getMethods
volatile Field[] declaredPublicFields;
volatile Method[] declaredPublicMethods;
volatile Class<?>[] interfaces;
}
构造方法 \ 成员变量 \ 成员方法的获取 都需要 先获取Class
//获取对应class的三个方法
Class<?> cls = Class.forName("路径包.类名");
Class<?> cls xxx.getClass();
Class<XXX> cls = XXX.class
常用方法
//获取构造器 public Constructor<T> getConstructor(Class<?>... parameterTypes); //获取某一个构造方法(公有)public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes); //暴力获取某一个构造方法(私有+公有)public Constructor<?>[] getConstructors(); //获取所有的构造方法(公有)public Constructor<?>[] getDeclaredConstructors(); //获取所有的构造方法(私有+公有)
//获取成员变量
public Field getField(String name); //根据成员变量名称获取一个成员变量(公有)public Field getDeclaredField(String name); //根据成员变量名称获取一个成员变量(私有 + 公有)public Field[] getFields(); //获取所有的成员变量(公有)public Field[] getDeclaredFields(); //获取所有的成员变量(私有 + 公有)
//获取成员方法
public Method getMethod(String name, Class<?>... parameterTypes); //根据方法名name, 方法参数列表类型parameterTypes 获取一个方法(公有)public Method getDeclaredMethod(String name, Class<?>... parameterTypes); //根据方法名name, 方法参数列表类型parameterTypes 获取一个方法(私有 + 公有)public Method[] getMethods(); //获取所有方法(公有)public Method[] getDeclaredMethods(); //获取所有方法(私有 + 公有)
Constructor构造方法
获取constructor
//获取无参构造方法
Constructor<?> constructor = cls.getConstructor();
//paramterTypes表示可变参数列表类型 如int.class, java.lang.String.class
public Constructor<T> getConstructor(Class<?>... parameterTypes);
public final class Constructor<T> extends Executable {
private Class<T> clazz;
private int slot;
private Class<?>[] parameterTypes;
private Class<?>[] exceptionTypes;
private int modifiers;
// Generics and annotations support
private transient String signature;
// generic info repository; lazily initialized
private transient ConstructorRepository genericInfo;
private byte[] annotations;
private byte[] parameterAnnotations;
}
常用方法
public T newInstance(Object ... initargs)//实例化对象 (参数列表)public String getName()//获取构造器名称public int getModifiers()//获取访问修饰符权限public void setAccessible(boolean flag) //对于私有构造器, 不执行访问权限检查
Field成员变量
Class<?> cls = Class.forName("Xxx");
Field xx = a.getDeclaredField("xx");
class Field extends AccessibleObject implements Member {
private Class<?> clazz;
private int slot;
// This is guaranteed to be interned by the VM in the 1.4
// reflection implementation
private String name;
private Class<?> type;
private int modifiers;
// Generics and annotations support
private transient String signature;
// generic info repository; lazily initialized
private transient FieldRepository genericInfo;
private byte[] annotations;
// Cached field accessor created without override
private FieldAccessor fieldAccessor;
// Cached field accessor created with override
private FieldAccessor overrideFieldAccessor;
}
常用方法
public int getModifiers() //获取访问修饰符public Class<?> getType() //获取成员变量类型public String getName() //获取成员变量名称public void set(Object obj, Object value) //对obj的成员变量赋值为value. 如果是static静态成员变量, obj可以是 [ Class<?> cls ]public Object get(Object obj) //获取obj的成员变量, 如果是static静态成员变量, obj可以是[ Class<?> cls ]public void setAccessible(boolean flag) //对于私有成员变量, 不执行访问权限检查
Method成员方法
Class<?> cls = Class.forName("Xxx");
Method xx = cls.getMethod("方法名xx", 可变形参列表(方法参数类型));
public final class Method extends Executable {
private Class<?> clazz;
private int slot;
// This is guaranteed to be interned by the VM in the 1.4
// reflection implementation
private String name;
private Class<?> returnType;
private Class<?>[] parameterTypes;
private Class<?>[] exceptionTypes;
private int modifiers;
// Generics and annotations support
private transient String signature;
// generic info repository; lazily initialized
private transient MethodRepository genericInfo;
private byte[] annotations;
private byte[] parameterAnnotations;
private byte[] annotationDefault;
private volatile MethodAccessor methodAccessor;
}
常用方法
public int getModifiers() //获取访问修饰符public String getName() //获取方法名称public Class<?> getReturnType() //获取返回值类型public Class<?>[] getParameterTypes() //获取参数列表类型public void setAccessible(boolean flag) //true为跳过访问权限检验public Object invoke(Object obj, Object... args) //执行方法(obj对象, args可变参数列表)
工厂案例
//BeanFactory.class
public class BeanFactory {
/**
* 获取bean类相应实例化对象
*
* @param className 类名
* @return 实例化对象
* @throws ClassNotFoundException 类型未找到异常
* @throws NoSuchMethodException 方法未找到异常
* @throws InvocationTargetException 方法调用异常
* @throws InstantiationException 构造器异常
* @throws IllegalAccessException 非法访问异常
*/
public static Object getBean(String className)
throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException,
InstantiationException, IllegalAccessException {
return Class.forName(className).getConstructor().newInstance();
}
}
//BeanUtils.class
public class BeanUtils {
/**
* 给bean的成员变量(基本类型)赋值
*
* @param bean bean实例化对象
* @param fieldName 成员变量名
* @param value 成员变量值
* @throws NoSuchFieldException 成员变量未找到异常
* @throws IllegalAccessException 非法访问异常
*/
public static void setProperty(Object bean, String fieldName, String value)
throws NoSuchFieldException, IllegalAccessException {
Class<?> cls = bean.getClass();
Field field = cls.getDeclaredField(fieldName);
Class<?> fieldType = field.getType();
final Object finalValue;
switch (fieldType.getName()) {
case "byte":
finalValue = Byte.parseByte(value);
break;
case "short":
finalValue = Short.parseShort(value);
break;
case "int":
finalValue = Integer.parseInt(value);
break;
case "long":
finalValue = Long.parseLong(value);
break;
case "float":
finalValue = Float.parseFloat(value);
break;
case "double":
finalValue = Double.parseDouble(value);
break;
case "char":
finalValue = value.charAt(0);
break;
case "boolean":
finalValue = Boolean.parseBoolean(value);
break;
case "java.lang.String":
finalValue = value;
break;
default:
finalValue = null;
}
field.setAccessible(true);
field.set(bean, finalValue);
}
/**
* 获取对象 成员变量的值
*
* @param bean bean对象
* @param fieldName 成员变量
* @return 返回成员变量的值
* @throws NoSuchFieldException 成员变量没找到异常
* @throws IllegalAccessException 非法访问异常
*/
public static String getProperty(Object bean, String fieldName)
throws NoSuchFieldException, IllegalAccessException {
Class<?> cls = bean.getClass();
Field field = cls.getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(bean).toString();
}
/**
* 将src的属性值 赋值给 dest的属性值
*
* @param srcBean 源bean
* @param destBean 目的bean
* @throws IllegalAccessException 非法访问权限异常
*/
public static void copyProperties(Object srcBean, Object destBean) throws IllegalAccessException {
Class<?> srcClass = srcBean.getClass();
Class<?> destClass = destBean.getClass();
if (srcClass != destClass) {
throw new ClassCastException();
}
Field[] fields = srcClass.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
/*
for (Field field : fields) {
field.set(destBean, field.get(srcBean));
}
*/
Arrays.stream(fields)
.forEach(field -> {
try {
field.set(destBean, field.get(srcBean));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
});
}
}