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 = 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 = 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通过反射注解赋值的更多相关文章
- 【Java EE 学习 24 下】【注解在数据库开发中的使用】【反射+注解+动态代理在事务中的应用service层】
一.使用注解可以解决JavaBean和数据库中表名不一致.字段名不一致.字段数量不一致的问题. 1.Sun公司给jdbc提供的注解 @Table.@Column.@Id.@OneToMany.@One ...
- java反射--注解的定义与运用以及权限拦截
自定义注解类编写的一些规则: 1. Annotation型定义为@interface, 所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是 ...
- 【译】8. Java反射——注解
原文地址:http://tutorials.jenkov.com/java-reflection/annotations.html ================================== ...
- Java学习:注解,反射,动态编译
狂神声明 : 文章均为自己的学习笔记 , 转载一定注明出处 ; 编辑不易 , 防君子不防小人~共勉 ! Java学习:注解,反射,动态编译 Annotation 注解 什么是注解 ? Annotat ...
- Java的反射和代理以及注解
最近接触到java的反射和代理(接触的有点迟了...),还是有必要总结下 1. Java的反射 有的时候我们需要在程序运行的时候获取类.方法等信息用于动态运行,这个时候反射就能够帮我们找到类.方法.成 ...
- java中的注解(Annotation)
转载:https://segmentfault.com/a/1190000007623013 简介 注解,java中提供了一种原程序中的元素关联任何信息.任何元素的途径的途径和方法. 注解是那些插入到 ...
- java之反射的基本介绍
什么是反射 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的以及动态调用对象的方法的功能称为Java的反射 ...
- Java中的注解基础
一.元注解 元注解的作用就是负责注解其他注解. 1.@Target @Target用来指明注解所修饰的目标,包括packages.types(类.接口.枚举.Annotation类型).类型成员(方法 ...
- java中的注解详解和自定义注解
一.java中的注解详解 1.什么是注解 用一个词就可以描述注解,那就是元数据,即一种描述数据的数据.所以,可以说注解就是源代码的元数据.比如,下面这段代码: @Override public Str ...
随机推荐
- Blazor和Vue对比学习(基础1.9):表单输入绑定和验证,VeeValidate和EditFrom
这是基础部分的最后一章,内容比较简单,算是为基础部分来个HappyEnding.我们分三个部分来学习: 表单输入绑定 Vue的表单验证:VeeValidate Blazor的表单验证:EditForm ...
- 204. Count Primes - LeetCode
Queston 204. Count Primes Solution 题目大意:给一个数,求小于这个数的素数的个数 思路:初始化一个boolean数组,初始设置为true,先遍历将2的倍数设置为fal ...
- vue ui 创建vue项目 没反应的解决办法 2021
1.升级vue 脚手架 即可 2.再 vue ui 创建项目 cnpm i -g @vue/cli
- 课堂练习——neo4j简单使用
启动neo4j: neo4j.bat console 进入neo4j数据库的conf目录下,编辑neo4j.conf文件:将当前数据库设置为你要建立的数据库名称(数据库不能重名): dbms.acti ...
- MMDeploy安装笔记
MMDeploy的TensorRT教程 Step1: 创建虚拟环境并且安装MMDetection conda create -n openmmlab python=3.7 -y conda activ ...
- SQL Server 2017 各版本之间的差异
SQL Server 2017的亮点 您选择的语言和平台 使用您选择的语言在本地和云中(现在在 Windows.Linux 和 Docker 容器上)构建现代应用程序. 行业领先的性能 充分利用任务关 ...
- 在CabloyJS中将Webpack生成的文件自动上传到阿里云OSS
背景 阿里云OSS提供了一个Webpack插件,可在Webpack打包结束后将webpack生成的文件自动上传到阿里云OSS中 下面看看在CabloyJS中如何使用该插件 新建项目,并配置MySQL连 ...
- Mac安装Brew包管理系统
Mac安装Brew包管理系统 前言 为什么需要安装brew 作为一个开发人员, 习惯了使用centos的yum和ubuntu的apt, 在mac中有没有这两个工具的平替? 有, 就是Brew. Bre ...
- CentOS中实现基于Docker部署BI数据分析
作为一个专业小白,咱啥都不懂. linux不懂,docker不懂. 但是我还想要完成领导下达的任务:在linux中安装docker后部署数据可视化工具.作为一名敬业 的打工人摆烂不可以,躺平不可以,弱 ...
- Mysql安装配置以及解决重装Mysql时忘记root password问题
目录 1.Mysql安装以及环境变量配置 重装Mysql时忘记root password问题 1.Mysql安装以及环境变量配置 官网安装:https://www.mysql.com/ 按 ...