JAVA反射

java反射

java反射就是在JVM执行javac后,项目在运行状态中,能够动态的获取.class中的属性(private,protected,public)对应的字段名称,属性值。反射类中的方法。这种动态的获取类中的属性和方法称之为反射机制。


以下代码包含反射获取类中的任何对象属性。

/**
 * @author BOBO
 * @Title: bobo_base
 * @Package com.bobo.base.reflected.dto
 * @Description: 反射DTO
 * @date 2018/3/13下午2:34
 */
@Data
@ApiModel("反射类DTO")
public class ReflectedDTO {

    private Integer id;

    private String name;

    public String smallName;

    protected String address;

    ReflectedDTO(String name){
        System.out.println("【protected】有Name参数的构造函数!name=" + name);
    }

    public ReflectedDTO(){
        System.out.println("【public】无参数的构造函数");
    }


    public ReflectedDTO(Integer id,String smallName){
        System.out.println("【public】有ID,smallName参数的构造函数!id=" + id + ",smallName=" + smallName);
    }

    private ReflectedDTO(Integer id){
        System.out.println("【private】有ID的参数的构造函数! id=" + id);
    }

    //*****************************成员方法***********************************************************
    public void show1(String s){
        System.out.println("调用了:公有的,String参数的show1(): s = " + s);
    }
    protected void show2(){
        System.out.println("调用了:受保护的,无参的show2()");
    }
    void show3(){
        System.out.println("调用了:默认的,无参的show3()");
    }
    private String show4(int age){
        System.out.println("调用了,私有的,并且有返回值的,int参数的show4(): age = " + age);
        return "abcd";
    }



}
/**
 * @author BOBO
 * @Title: bobo_base
 * @Package com.bobo.reflected.reflectedImpl
 * @Description: 反射Service
 * @date 2018/3/12下午3:05
 */
@Service
public class ReflectedService {


    /**
     *   * @Description: 反射获取方法(获取对象中的属性值)
     *   * @param list
     *   * @return
     *   * @author BOBO
     *   * @date 2018/3/11 下午9:52
     *
     */
    public <T> boolean reflectedMethod(T t) throws IntrospectionException, InvocationTargetException, IllegalAccessException {

        Class<?> aClass = t.getClass();
        //获取所有字段的Property
        // PropertyDescriptor[] targetPds = BeanUtils.getPropertyDescriptors(aClass);
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {

            //获取当前字段的所有Property
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), aClass);

            //获取当前字段的getter方法
            Method readMethod = propertyDescriptor.getReadMethod();

            //如果getter的权限不为public,则修改accessible为true
            if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
                readMethod.setAccessible(true);
            }
            //调用getter获得值,如果这个值为空则跳过
            Object value = readMethod.invoke(t);
            if (value == null) {
                continue;
            }

            System.out.println(value.toString());

            //如果当前字段类型为List
            if (propertyDescriptor.getPropertyType().getName().equals(List.class.getName())) {
                List<?> list = (List<?>) value;
                list.forEach(dto -> {
                    System.err.println(dto.toString());
                });

            }


        }


        return true;

    }

    /**
     * 通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员;
     *
     * 1.获取构造方法:
     *      1).批量的方法:
     *          public Constructor[] getConstructors():所有"公有的"构造方法
                public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)

     *      2).获取单个的方法,并调用:
     *          public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
     *          public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
     *
     *          调用构造方法:ß
     *          Constructor-->newInstance(Object... initargs)
     */
    public void constructorsHandel(Class<?> classz) throws Exception {

        //通过Class.forName获取类对象
        Class classzz = Class.forName(classz.getName());


        System.out.println("**********************所有公有构造方法*********************************");
        //获取所有public标识的构造函数
        Constructor[] constructors = classzz.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

        System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************");
        //获取所有构造函数
        Constructor[] declaredConstructors = classzz.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

        System.out.println("*****************获取公有、空的构造方法*******************************");
        Constructor constructor = classzz.getConstructor(null);
        //1>、因为是无参的构造方法所以类型是一个null,不写也可以:这里需要的是一个参数的类型,切记是类型
        //2>、返回的是描述这个无参构造函数的类对象
        System.out.println(constructor);

        //表示创建一个空的构造函数
        constructor.newInstance();

        System.out.println("******************获取公有构造方法,并调用*******************************");
        //获取构造函数中参数为(Integer,String)对象实例
        Constructor declaredConstructor = classzz.getDeclaredConstructor(Integer.class, String.class);
        //newInstance能输出信息是因为此构造函数是public标识,
        declaredConstructor.newInstance(123, "张三");

        /**
         * newInstance(Object... initargs)
             使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
             它的返回值是T类型,所以newInstance是创建了一个构造方法的声明类的新实例对象。并为之调用
         */
        System.out.println("******************获取私有构造方法,并调用*******************************");
        //如果为私有方法标识,需要如下设置。否则不能正常执行反射操作
        //需要设置 privateConstructor.setAccessible(true);
        Constructor privateConstructor = classzz.getDeclaredConstructor(Integer.class);
        //暴力访问(忽略掉访问修饰符)
        privateConstructor.setAccessible(true);
        privateConstructor.newInstance(333);


    }

    /*
     * 获取成员变量并调用:
     *
     * 1.批量的
     *      1).Field[] getFields():获取所有的"公有字段"
     *      2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
     * 2.获取单个的:
     *      1).public Field getField(String fieldName):获取某个"公有的"字段;
     *      2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
     *
     *   设置字段的值:
     *      Field --> public void set(Object obj,Object value):
     *                  参数说明:
     *                  1.obj:要设置的字段所在的对象;
     *                  2.value:要为字段设置的值;
     *
     */
    public <T> void filedHandle(T classz) throws Exception{

        //通过getClass方式获取对象
        Class<?> classzz = classz.getClass();
        System.out.println("************获取所有公有的字段********************");
        Field[] fields = classzz.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        System.out.println("************获取所有的字段********************");
        fields = classzz.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        System.out.println("*************获取字段**并调用【1】***********************************");
        fields = classzz.getDeclaredFields();

        for (Field field : fields) {
            //获取当前字段的所有Property
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), classzz);
            //获取当前字段的读属性 (getXXX)
            Method readMethod = propertyDescriptor.getReadMethod();
            //将当前字段设置为公有属性
            field.setAccessible(true);
            //通过Method获取属性值
            Object value = readMethod.invoke(classz);
            System.out.println(value);

        }

        //重定向值
        for (Field field : fields) {
            //获取当前字段的所有Property
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), classzz);
            //获取当前字段的写属性 (setXXX)
            Method writeMethod = propertyDescriptor.getWriteMethod();
            //获取名称
            String name = writeMethod.getName();
            //如果是smallName 重定向值 【公有字段】
            if(name.equals("setSmallName")){
                //获取setXXX 重新赋值
                writeMethod.invoke(classz,"11");
            }

            //【私有字段】 需要添加setAccessible(true);
            if(name.equals("setName")){
                //将当前字段设置为公有属性
                field.setAccessible(true);
                //获取setXXX 重新赋值
                writeMethod.invoke(classz,"重定向名称");
            }

        }

        System.out.println("*************获取字段**并调用【2】***********************************");

        //获取已知字段
        Field id = classzz.getDeclaredField("id");
        //获取单独的字段值
//        id.setAccessible(true);
//        System.out.println(id.get(classz));


        //获取对象 类似 ReflectedDTO o = new ReflectedDTO();
        //这样newInstance()代表创建一个无参的构造函数,也可以在newInstance()括弧中添加参数
        Object o = classzz.getConstructor().newInstance();
        //解除私有限定
        id.setAccessible(true);
        id.set(o,999);
        //强转类型 (此处强转是为了输出)
        ReflectedDTO reflectedDTO = (ReflectedDTO)o;
        System.out.println("第二种方式重置字段ID值为:" + reflectedDTO.getId());

    }


    /*
     * 获取成员变量并调用:
     *
     * 1.批量的
     *      1).Field[] getFields():获取所有的"公有字段"
     *      2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
     * 2.获取单个的:
     *      1).public Field getField(String fieldName):获取某个"公有的"字段;
     *      2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
     *
     *   设置字段的值:
     *      Field --> public void set(Object obj,Object value):
     *                  参数说明:
     *                  1.obj:要设置的字段所在的对象;
     *                  2.value:要为字段设置的值;
     *
     */
    public void methodHandel(Class<?> classz) throws Exception{

        Class<?> aClass = Class.forName(classz.getName());

        System.out.println("***************获取所有的”公有“方法*******************");
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

        System.out.println("***************获取所有的”私有“方法*******************");
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }

        System.out.println("***************获取私有的show4()方法******************");
        Method method = aClass.getDeclaredMethod("show4", int.class);
        method.setAccessible(true);
        Object o = aClass.getConstructor().newInstance();
        method.invoke(o,567);


    }

}
    /**
       * @Description: 反射应用
       * @param
       * @return
       * @author BOBO
       * @date 2018/3/12 下午3:11
       */
    private void reflectedMethod() throws Exception {
//      List<Data1> list = new ArrayList<>();
//      Data1 data1 = new Data1();
//      data1.setGetInfo2("23232");
//      data1.setId(23);
//      data1.setInfo1("44444");
//      list.add(data1);
//
//      GenericDTO genericDTO = new GenericDTO();
//      genericDTO.setClassName("老哈迪斯");
//      genericDTO.setClassPath("path");
//      genericDTO.setId(345);
//      genericDTO.setClassType("classType领导来了");
//      genericDTO.setClassInfo(list);
//
//      reflectedService.reflectedMethod(genericDTO);

        //获取构造函数的反射对象方法
//      reflectedService.constructorsHandel(ReflectedDTO.class);

//      ReflectedDTO reflectedDTO = new ReflectedDTO();
//      reflectedDTO.setId(222);
//      reflectedDTO.setAddress("张家口");
//      reflectedDTO.setName("李四");
//      reflectedDTO.setSmallName("小四");
//
//      //获取队形属性方法
//      reflectedService.filedHandle(reflectedDTO);

        reflectedService.methodHandel(ReflectedDTO.class);
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值