Java反射总结

本文详细介绍了Java反射机制的核心类,如Class、Constructor、Field和Method,包括它们的获取方式、常用方法以及在工厂模式(如BeanFactory和BeanUtils)中的应用,展示了如何通过反射操作字节码文件和处理访问权限。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述 

包名: 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);
                    }
                });

    }
    


}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值