您的位置 首页 java

Java通过反射注解赋值

问题描述

查询公司列表,分别是公司id、区域id、区域名称:

Java通过反射注解赋值

创建公司类 Company

 public class Company {

    public Company(Integer id,   Integer  areaId,  String  areaName) {
        this.id = id;
        this.areaId = areaId;
        this.areaName = areaName;
    }

    /**
     * 公司id
     */    private Integer id;

    /**
     * 区域id
     */    private Integer areaId;

    /**
     * 区域名称
     */    private String areaName;
     
    // 省略get/set方法 

}
  

最终解决

要求 汇总 各个区域公司数量,得到如下汇总:

最终区域实体 AreaStatistic :

 public class AreaStatistic {

    @ColumnProperty("华东大区")
    private Integer eastChina = 0;

    @ColumnProperty("华东id")
    private Integer eastChinaId;

    @ColumnProperty("华南大区")
    private Integer southChina = 0;

    @ColumnProperty("华南id")
    private Integer southChinaId;

    @ColumnProperty(" 华北 大区")
    private Integer northChina = 0;

    @ColumnProperty("华北id")
    private Integer northChinaId;

    @Override
    public String toString() {
        return "AreaStatistic{n" +
                "华东Id=" + eastChinaId +
                ",华东=" + eastChina +
                ", n华南Id=" + southChinaId +
                ", 华南=" + southChina +
                ", n华北Id=" + northChinaId +
                ", 华北=" + northChina +
                '}';
    }
    // 省略get/set方法
}
  

if/else 普通解法

 AreaStatistic areaStatistic = new AreaStatistic();
for (Company company:companyList) {
    String areaName = company.getAreaName();
    if ("华南".equals(areaName)) {
        areaStatistic.setSouthChina(areaStatistic.getSouthChina()+1);
        areaStatistic.setSouthChinaId(company.getAreaId());
    } else if ("华北".equals(areaName)) {
        areaStatistic.setNorthChina(areaStatistic.getNorthChina()+1);
        areaStatistic.setNorthChinaId(company.getAreaId());
    } else if ("华东".equals(areaName)) {
        areaStatistic.setEastChina(areaStatistic.getEastChina()+1);
        areaStatistic.setEastChinaId(company.getAreaId());
    }
}
  

输出:

 华东Id=3,华东=2, 
华南Id=1, 华南=1, 
华北Id=2, 华北=2
  

这种做法的缺点:

  • 要写大量的条件判断语句,非常的繁琐。
  • 增加和减少统计区域,都要修改代码。

针对上面的缺点,使用反射获取注解,通过注解获取属性赋值。

通过反射注解赋值属性

解题思路

  1. 遍历公司列表,获取到区域id和区域名称。
  2. 创建自定义注解 @ColumnProperty :
 @Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnProperty {

    String value() default "";

}
  
  1. 通过反射获取属性,然后遍历字段属性获取注解。

AreaStatistic 字段属性上添加注解:

 @ColumnProperty("华东大区")
private Integer eastChina = 0;

@ColumnProperty("华东id")
 private  Integer eastChinaId;

@ColumnProperty("华南大区")
private Integer southChina = 0;

@ColumnProperty("华南id")
private Integer southChinaId;

@ColumnProperty("华北大区")
private Integer northChina = 0;

@ColumnProperty("华北id")
private Integer northChinaId;
  
  1. 通过反射获取属性,然后遍历字段属性获取注解。
 Class  static Class = areaStatistic.getClass();
Field[] fields = staticClass.getDeclaredFields();
for (Field field : fields) {
    ColumnProperty property = field.get Annotation (ColumnProperty.class);
    String value = property.value();
}
  
  1. 匹配区域名称和字段属性,比如遍历公司区域是 华东 ,就遍历到 华东大区 注解对应的字段,并赋值或者获取字段值。
 if (value != null) {
    int indexOf = value.indexOf("大区");
    if (indexOf != -1 && value.length() == 4) {
        if (areaName.equals(value.substring(0,2))) {
            field.setAccessible(true);
            field.set(areaStatistic,(Integer) field.get(areaStatistic) + 1);  
        }
     }
}
  
  1. 区域id赋值也是相同的解题思路。

根据上面的思路,有如下 代码汇总

 // 遍历公司
for (Company company:companyList) {
  setAreaProperty(areaStatistic2,company.getAreaName(),company.getAreaId());
}

private  void  setAreaProperty(AreaStatistic areaStatistic,String areaName,Integer areaId) throws IllegalAccess Exception  {
    // 反射获取注解 
    Class staticClass = areaStatistic.getClass();
    Field[] fields = staticClass.getDeclaredFields();
    for (Field field : fields) {
        ColumnProperty property = field.getAnnotation(ColumnProperty.class);
        String value = property.value();
        if (value != null) {
            int indexOf = value.indexOf("大区");
            if (indexOf != -1 && value.length() == 4) {
                // 匹配到 注解 属性并赋值 
                if (areaName.equals(value.substring(0,2))) {
                    field.setAccessible(true);
                    field.set(areaStatistic,(Integer) field.get(areaStatistic) + 1);
                    for (Field idField : fields) {
                        ColumnProperty idProperty = idField.getAnnotation(ColumnProperty.class);
                        String idValue = idProperty.value();
                        if (idValue.equals(areaName+"id")) {
                            idField.setAccessible(true);
                            idField.set(areaStatistic,areaId);
                            break;
                        }
                    }
                    break;
                }
            }
        }
    }
}
  

输出:

 华东Id=3,华东=2, 
华南Id=1, 华南=1, 
华北Id=2, 华北=2
  

汇总某些字段的和

上面算出各个区域的汇总之后,还要算出全部区域的总和,这里还是使用到注解,把属性字段包含 大区 都累加起来:

 AreaStatistic statistic = new AreaStatistic();
statistic.setEastChina(2);
statistic.setNorthChina(3);
statistic.setSouthChina(1);
int sum = 0;
Class staticClass = statistic.getClass();
Field[] fields = staticClass.getDeclaredFields();
for (Field field : fields) {
    ColumnProperty property = field.getAnnotation(ColumnProperty.class);
    String value = property.value();
    if (value.indexOf("大区") != -1) {
        field.setAccessible(true);
        sum += field.get(statistic) == null ? 0 : (Integer) field.get(statistic);
    }
}
System.out.println(sum);
  

输出结果:

 6
  

总结

  • 自定义注解,通过反射获取注解
  • 通过匹配注解值,获取或者复制对应的字段属性。

赋值主要代码为:

 field.setAccessible(true);
field.set(Model,value);
  

源码地址

文章来源:智云一二三科技

文章标题:Java通过反射注解赋值

文章地址:https://www.zhihuclub.com/188612.shtml

关于作者: 智云科技

热门文章

网站地图