zoukankan      html  css  js  c++  java
  • 利用反射操作bean的属性和方法

    今天在开发中碰到这样一个场景:当请求添加项目下的目录时,传过来的是一个IndexModel,这个Model里有关于这个目录字段的详细信息,包括基础报表,实时,漏斗等信息(这些字段类型都是boolean),对应于页面上生成目录的多选框。现要将这些配置存入数据库,在数据库中存的是这个项目下的目录,比如说在页面勾选了基础报表这个选择框,就会在数据库中的menu表插入一条数据记录这个配置。这样一来,就需要对传递过来的这个IndexModel类的属性值进行判断,再决定插入数据库的信息。

        下面是IndexModel这个model的基本属性:

     1 public class IndexModel {
     2     private Boolean basic_report;  //基础报表
     3     private Boolean realtime;   //实时
     4     private Boolean event; //事件
     5     private Boolean retain;// 留存
     6     private Boolean funnel; //漏斗
     7     private Boolean explore; //探索
     8     private Boolean grouping; //分组
     9     private Boolean user_portrait; //用户画像
    10     private Boolean log; //日志
    11 
    12     //setters and getters ..
    13 }

    当某个属性为true时,则就会将这个属性配置进数据库,当这个属性为false时,则不会进行任何操作。

    由此,我想到了利用Java反射,遍历这个类的属性,然后获取到这个属性的名字和值判断,再映射成数据库表的字段,插入到数据库中去。

     我们先上解决方案代码:

     1  Field[] fields = IndexModel.class.getDeclaredFields();
     2             for (int i = 0; i < fields.length; i++) {
     3                     Field f = fields[i];
     4                     f.setAccessible(true); // 设置这些属性是可以访问的
     5                     try {
     6                        if(f.getGenericType().toString().endsWith("Boolean") && (Boolean) f.get(indexModel) == true) { // 得到此属性的值
     7                             IndexDto indexDto = parseIndexModelToDto(indexModel, f.getName());
     8                             projectService.addIndex(indexDto);
     9                         }
    10                     } catch (IllegalAccessException e) {
    11                         logger.error("属性类型转换异常");
    12                     }
    13                 }

    在代码中先是利用反射获取类的所有对象成员的字段值,在这里由于IndexModel中的属性字段值都是private的,所以,只能使用 getDeclaredFields()获取到这些字段,至于getFields()方法,只能获取到类(及其父类)中的公有成员,这两个方法返回的都是Field类型的数组。

    在获取私有成员值之前,必须调用setAccessible(true),否则的话,将会抛出异常:java.lang.IllegalAccessException:  class... can not access ,显示不能获取字段值。

    另外,在需要获取成员的类型时,需要调用相应的field的getType()方法,获取field的类型有如下几种方法

    1  Class<?> type = field.getType();        // 通过这种方式只对普通类型的Field有效,如果该Field的类型是有泛型限制的类型,如Map<String,Integer>类型,则不能准确得到该Field的泛型参数。
    2 
    3  Type type = field.getGenericType();  // 为了获得指定Field的泛型类型,应该使用这个方法来获取指定Field的泛型类型

    如果要获取上面对应field的被泛型限制的方法,就需要将上面的type对象强制类型转换成ParameterizedType对象,ParameterizedType代表被参数化的类型,也就是增加了泛型限制的类型,ParameterizedType类提供了两个方法:

        getRawType();                            返回被泛型限制的类型;

        getActualTypeArguments();        返回泛型参数类型。   

    然后,要获取成员变量的名称直接使用field.getName(),但是属性值则是field.get(Object),这个object是该field所属的!

    最后,要是想为这个成员变量设置值,则需要调用set:field[i].set(indexModel , true);

  • 相关阅读:
    Educational Codeforces Round 67 D. Subarray Sorting
    2019 Multi-University Training Contest 5
    Educational Codeforces Round 69 (Rated for Div. 2) E. Culture Code
    Educational Codeforces Round 69 D. Yet Another Subarray Problem
    2019牛客暑期多校训练第六场
    Educational Codeforces Round 68 E. Count The Rectangles
    2019牛客多校第五场题解
    2019 Multi-University Training Contest 3
    2019 Multi-University Training Contest 2
    [模板] 三维偏序
  • 原文地址:https://www.cnblogs.com/jy107600/p/7150976.html
Copyright © 2011-2022 走看看