Java通過反射注解賦值的方法詳解
前段時間,領(lǐng)導(dǎo)分配一個統(tǒng)計(jì)銷售區(qū)域匯總的數(shù)據(jù),解決方案使用到了反射獲取注解,通過注解獲取屬性或者設(shè)置字段屬性。
問題描述
查詢公司列表,分別是公司id、區(qū)域id、區(qū)域名稱:
| 公司id | 區(qū)域id | 區(qū)域名稱 |
|---|---|---|
| 1 | 1 | 華南 |
| 2 | 2 | 華北 |
| 3 | 2 | 華北 |
| 4 | 3 | 華東 |
| 5 | 3 | 華東 |
創(chuàng)建公司類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;
/**
* 區(qū)域id
*/
private Integer areaId;
/**
* 區(qū)域名稱
*/
private String areaName;
// 省略get/set方法
}
最終解決
要求匯總各個區(qū)域公司數(shù)量,得到如下匯總:
| 區(qū)域id | 區(qū)域名稱 | 公司總數(shù) |
|---|---|---|
| 1 | 華南 | 1 |
| 2 | 華北 | 2 |
| 3 | 華東 | 2 |
最終區(qū)域?qū)嶓wAreaStatistic:
public class AreaStatistic {
@ColumnProperty("華東大區(qū)")
private Integer eastChina = 0;
@ColumnProperty("華東id")
private Integer eastChinaId;
@ColumnProperty("華南大區(qū)")
private Integer southChina = 0;
@ColumnProperty("華南id")
private Integer southChinaId;
@ColumnProperty("華北大區(qū)")
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
這種做法的缺點(diǎn):
- 要寫大量的條件判斷語句,非常的繁瑣。
- 增加和減少統(tǒng)計(jì)區(qū)域,都要修改代碼。
針對上面的缺點(diǎn),使用反射獲取注解,通過注解獲取屬性賦值。
通過反射注解賦值屬性
解題思路
1.遍歷公司列表,獲取到區(qū)域id和區(qū)域名稱。
2.創(chuàng)建自定義注解@ColumnProperty:
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnProperty {
String value() default "";
}
3.通過反射獲取屬性,然后遍歷字段屬性獲取注解。
在AreaStatistic字段屬性上添加注解:
@ColumnProperty("華東大區(qū)")
private Integer eastChina = 0;
@ColumnProperty("華東id")
private Integer eastChinaId;
@ColumnProperty("華南大區(qū)")
private Integer southChina = 0;
@ColumnProperty("華南id")
private Integer southChinaId;
@ColumnProperty("華北大區(qū)")
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.匹配區(qū)域名稱和字段屬性,比如遍歷公司區(qū)域是華東,就遍歷到華東大區(qū)注解對應(yīng)的字段,并賦值或者獲取字段值。
if (value != null) {
int indexOf = value.indexOf("大區(qū)");
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.區(qū)域id賦值也是相同的解題思路。
根據(jù)上面的思路,有如下代碼匯總:
// 遍歷公司
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("大區(qū)");
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
匯總某些字段的和
上面算出各個區(qū)域的匯總之后,還要算出全部區(qū)域的總和,這里還是使用到注解,把屬性字段包含大區(qū)都累加起來:
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("大區(qū)") != -1) {
field.setAccessible(true);
sum += field.get(statistic) == null ? 0 : (Integer) field.get(statistic);
}
}
System.out.println(sum);
輸出結(jié)果:
6
總結(jié)
1.自定義注解,通過反射獲取注解
2.通過匹配注解值,獲取或者復(fù)制對應(yīng)的字段屬性。
賦值主要代碼為:
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: 通過注解設(shè)值
*/
public class SetValueByAnnotation {
/**
* 通過屬性賦值
*/
@Test
public void test() throws IllegalAccessException {
// 添加數(shù)據(jù)
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("大區(qū)");
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;
}
}
}
}
}
/**
* 根據(jù)注解累加字段值
*/
@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("大區(qū)") != -1) {
field.setAccessible(true);
sum += field.get(statistic) == null ? 0 : (Integer) field.get(statistic);
}
}
System.out.println(sum);
}
}到此這篇關(guān)于Java通過反射注解賦值的方法詳解的文章就介紹到這了,更多相關(guān)Java反射注解賦值內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring boot項(xiàng)目中異常攔截設(shè)計(jì)和處理詳解
這篇文章主要介給大家紹了關(guān)于Spring boot項(xiàng)目中異常攔截設(shè)計(jì)和處理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用spring boot具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起看看吧2018-12-12
Java中Bigdecimal類的toString()方法和toPlainString()方法區(qū)別
BigDecimal類有多個方法可以將其轉(zhuǎn)換為字符串,其中包括toString()和toPlainString(),本文主要介紹了Java中Bigdecimal類的toString()方法和toPlainString()方法區(qū)別,具有一定的參考價值,感興趣的可以了解一下2024-07-07
SpringBoot接收參數(shù)所有方式總結(jié)
這篇文章主要介紹了SpringBoot接收參數(shù)所有方式總結(jié),文中通過代碼示例和圖文結(jié)合的方式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-07-07
Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(37)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你2021-07-07
關(guān)于springboot整合swagger問題及解決方法
這篇文章主要介紹了關(guān)于springboot整合swagger問題及解決方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-04-04
Springboot AOP對指定敏感字段數(shù)據(jù)加密存儲的實(shí)現(xiàn)
本篇文章主要介紹了利用Springboot+AOP對指定的敏感數(shù)據(jù)進(jìn)行加密存儲以及對數(shù)據(jù)中加密的數(shù)據(jù)的解密的方法,代碼詳細(xì),具有一定的價值,感興趣的小伙伴可以了解一下2021-11-11
Java?Git?Commit?Message使用規(guī)范
這篇文章主要介紹了Java?Git?Commit?Message使用規(guī)范,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下,希望對你的學(xué)習(xí)有所幫助2022-08-08
Springboot視頻接口報大量的ClientAbortException找不到原因的解決
本文主要介紹了Springboot視頻接口報大量的ClientAbortException找不到原因的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08

