Java反射注解赋值
小码code 人气:0前段时间,领导分配一个统计销售区域汇总的数据,解决方案使用到了反射获取注解,通过注解获取属性或者设置字段属性。
问题描述
查询公司列表,分别是公司id、区域id、区域名称:
公司id | 区域id | 区域名称 |
---|---|---|
1 | 1 | 华南 |
2 | 2 | 华北 |
3 | 2 | 华北 |
4 | 3 | 华东 |
5 | 3 | 华东 |
创建公司类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方法 }
最终解决
要求汇总各个区域公司数量,得到如下汇总:
区域id | 区域名称 | 公司总数 |
---|---|---|
1 | 华南 | 1 |
2 | 华北 | 2 |
3 | 华东 | 2 |
最终区域实体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 ""; }
3.通过反射获取属性,然后遍历字段属性获取注解。
在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;
4.通过反射获取属性,然后遍历字段属性获取注解。
Class staticClass = areaStatistic.getClass(); Field[] fields = staticClass.getDeclaredFields(); for (Field field : fields) { ColumnProperty property = field.getAnnotation(ColumnProperty.class); String value = property.value(); }
5.匹配区域名称和字段属性,比如遍历公司区域是华东,就遍历到华东大区注解对应的字段,并赋值或者获取字段值。
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); } } }
6.区域id赋值也是相同的解题思路。
根据上面的思路,有如下代码汇总:
// 遍历公司 for (Company company:companyList) { setAreaProperty(areaStatistic2,company.getAreaName(),company.getAreaId()); } private void setAreaProperty(AreaStatistic areaStatistic,String areaName,Integer areaId) throws IllegalAccessException { // 反射获取注解 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
总结
1.自定义注解,通过反射获取注解
2.通过匹配注解值,获取或者复制对应的字段属性。
赋值主要代码为:
field.setAccessible(true); field.set(Model,value);
源码
package reflect; import org.junit.Test; import reflect.annotation.ColumnProperty; import reflect.model.AreaStatistic; import reflect.model.Company; import javax.print.DocFlavor; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; /** * @Author: laizc * @Date: created in 2022-07-21 * @desc: 通过注解设值 */ public class SetValueByAnnotation { /** * 通过属性赋值 */ @Test public void test() throws IllegalAccessException { // 添加数据 Company company5 = new Company(1,1,"华南"); Company company1 = new Company(2,2,"华北"); Company company2 = new Company(3,2,"华北"); Company company3 = new Company(4,3,"华东"); Company company4 = new Company(5,3,"华东"); List<Company> companyList = new ArrayList<>(); companyList.add(company5); companyList.add(company1); companyList.add(company2); companyList.add(company3); companyList.add(company4); // 解法1 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()); } } System.out.println(areaStatistic); // 解法二 AreaStatistic areaStatistic2 = new AreaStatistic(); for (Company company:companyList) { setAreaProperty(areaStatistic2,company.getAreaName(),company.getAreaId()); } System.out.println(areaStatistic2); } private void setAreaProperty(AreaStatistic areaStatistic,String areaName,Integer areaId) throws IllegalAccessException { 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; } } } } } /** * 根据注解累加字段值 */ @Test public void accumulate() throws IllegalAccessException { 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); } }
加载全部内容