前段时间,领导赋值了一个销售区域数据的统计汇总。方案使用反射获取注解,通过注解获取属性或设置字段属性。问题描述查询公司列表,分别是公司id、地区id、地区名称:公司id地区id地区名称11华南22华北32华北43华东53华东创建公司类公司:公有类公司{publicCompany(Integerid,IntegerareaId,StringareaName){this.id=id;this.areaId=areaId;this.areaName=areaName;}/***公司id*/privateIntegerid;/***区域ID*/privateIntegerareaId;/***区域名称*/privateStringareaName;//省略get/set方法}最终的解决方案需要汇总每个区域的企业数量,得到如下汇总:区域id区域名称企业总数1华南12华北23华东2finalregionentityAreaStatistic:publicclassAreaStatistic{@ColumnProperty("华东地区")privateIntegereastChina=0;@ColumnProperty("华东id")privateIntegereastChinaId;@ColumnProperty("华南地区")privateIntegersouthChina=0;@ColumnProperty("华南id")privateIntegersouthChinaId;@ColumnProperty("华北地区")privateIntegernorthChina=0;@ColumnProperty("华北id")privateIntegernorthChinaId;@覆盖epublicStringtoString(){return"AreaStatistic{\n"+"EastChinaId="+eastChinaId+",EastChina="+eastChina+",\nSouthChinaId="+southChinaId+",SouthChina="+southChina+",\n华北Id="+northChinaId+",华北="+northChina+'}';}//省略get/set方法}if/else通用解AreaStatisticareaStatistic=newAreaStatistic();for(Companycompany:companyList){StringareaName=company.getAreaName();if("华南".equals(areaName)){areaStatistic.setSouthChina(areaStatistic.getSouthChina()+1);areaStatistic.setSouthChinaId(company.getAreaId());}elseif("华北".equals(areaName)){areaStatistic.setNorthChina(areaStatistic.getNorthChina()+1);areaStatistic.setNorthChinaId(company.getAreaId());}elseif("华东".equals(地区名称)){areaStatistic.setEastChina(areaStatistic.getEastChina()+1);areaStatistic.setEastChinaId(company.getAreaId());}}输出:华东Id=3,华东Id=2,华南Id=1,华南=1,华北Id=2,华北Id=2这种方式的缺点:需要写一个大数条件判断语句,增加和减少统计区域非常繁琐,必须修改代码。针对以上不足,使用反射获取注解,通过注解获取属性赋值。通过反映注解赋值属性遍历公司列表解决问题,得到区域id和区域名称。创建自定义注解@ColumnProperty:@Target({ElementType.METHOD,ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)public@interfaceColumnProperty{Stringvalue()default"";}通过反射获取属性,然后遍历fieldproperties获取注解。为AreaStatistic字段属性添加注解:@ColumnProperty("华东地区")privateIntegereastChina=0;@ColumnProperty("华东id")privateIntegereastChinaId;@ColumnProperty("华南地区")privateIntegersouthChina=0;@ColumnProperty("华北id")privateIntegersouthChinaId;@ColumnProperty("华北地区")privateIntegernorthChina=0;@ColumnProperty("华北id")privateIntegernorthChinaId;通过反射获取属性,然后遍历字段属性获取注解。ClassstaticClass=areaStatistic.getClass();Field[]fields=staticClass.getDeclaredFields();for(Fieldfield:fields){ColumnProperty属性=field.getAnnotation(ColumnProperty.class);Stringvalue=property.value();}匹配区域名称和字段属性。比如遍历公司地域为华东时,则遍历到华东地域标注对应的字段,赋值或获取该字段值。if(value!=null){intindexOf=value.indexOf("大面积");如果(indexOf!=-1&&value.length()==4){如果(areaName.equals(value.substring(0,2))){field.setAccessible(true);field.set(areaStatistic,(Integer)field.get(areaStatistic)+1);}}}区域id赋值也是同样的解题思路。根据上面的思路,有如下代码总结://遍历公司for(Companycompany:companyList){setAreaProperty(areaStatistic2,company.getAreaName(),company.getAreaId());}privatevoidsetAreaProperty(AreaStatisticareaStatistic,StringareaName,IntegerareaId)throwsIllegalAccessException{//反射获取注解ClassstaticClass=areaStatistic.getClass();Field[]fields=staticClass.getDeclaredFields();for(Fieldfield:fields){ColumnPropertyproperty=field.getAnnotation(ColumnProperty.class);字符串值=property.value();if(value!=null){intindexOf=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);对于(字段idField:字段){ColumnPropertyidProperty=idField.getAnnotation(ColumnProperty.class);StringidValue=idProperty.value();如果(idValue.equals(areaName+"id")){idField.setAccessible(true);idField.set(areaStatistic,areaId);休息;}}休息;}}}}}Output:ChinaEastId=3,ChinaEast=2,ChinaSouthId=1,ChinaSouth=1,ChinaNorthId=2,ChinaNorth=2汇总一些字段,计算每个字段的值上面的面积汇总后,需要计算所有面积的总和。这里还是要注意把大面积的属性字段加起来:AreaStatisticstatistic=newAreaStatistic();statistic.setEastChina(2);statistic.setNorthChina(3);statistic.setSouthChina(1);intsum=0;ClassstaticClass=statistic.getClass();Field[]fields=staticClass.getDeclaredFields();for(Fieldfield:fields){ColumnPropertyproperty=field.getAnnotation(ColumnProperty.class);字符串值=property.value();如果(value.indexOf("largearea")!=-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);源码地址https://github.com/jeremylai7/java-codes/blob/master/basis/src/main/java/reflect/SetValueByAnnotation.java
