前段时间,领导分配一个统计销售区域汇总的数据,解决方案使用到了反射获取注解,通过注解获取属性或者设置字段属性。问题描述 【Java通过反射注解赋值】查询公司列表,分别是公司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
这种做法的缺点:
- 要写大量的条件判断语句,非常的繁琐。
- 增加和减少统计区域,都要修改代码。
通过反射注解赋值属性 解题思路
- 遍历公司列表,获取到区域id和区域名称。
- 创建自定义注解
@ColumnProperty
:
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnProperty {String value() default "";
}
- 通过反射获取属性,然后遍历字段属性获取注解。
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;
- 通过反射获取属性,然后遍历字段属性获取注解。
Class staticClass = areaStatistic.getClass();
Field[] fields = staticClass.getDeclaredFields();
for (Field field : fields) {
ColumnProperty property = field.getAnnotation(ColumnProperty.class);
String value = https://www.it610.com/article/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);
}
}
}
- 区域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 = https://www.it610.com/article/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 = https://www.it610.com/article/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 = https://www.it610.com/article/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);
源码地址 https://github.com/jeremylai7/java-codes/blob/master/basis/src/main/java/reflect/SetValueByAnnotation.java
推荐阅读
- Jackson 解析 JSON 详细教程
- Outh2|【OAuth2】三、OAuth2配置解读
- JAVA|IDEA导出Springboot包(附加本地库)
- Java|基于 Spring Cloud 开发的分布式系统,遇到爬虫、接口盗刷怎么办
- JAVA工具类时间处理类DateUtils
- Z00334 轻量级JAVAEE企业应用实战(第3版) 百度网盘链接
- 利用Java将word文件转成pdf文件
- Java|将maven项目导出jar包
- maven|怎么使用okhttp的form-data数据类型对接接口