Java通過反射注解賦值的方法詳解
前段時(shí)間,領(lǐng)導(dǎo)分配一個(gè)統(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方法 }
最終解決
要求匯總各個(gè)區(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
匯總某些字段的和
上面算出各個(gè)區(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í)價(jià)值,需要的朋友們下面隨著小編來一起看看吧2018-12-12Java中Bigdecimal類的toString()方法和toPlainString()方法區(qū)別
BigDecimal類有多個(gè)方法可以將其轉(zhuǎn)換為字符串,其中包括toString()和toPlainString(),本文主要介紹了Java中Bigdecimal類的toString()方法和toPlainString()方法區(qū)別,具有一定的參考價(jià)值,感興趣的可以了解一下2024-07-07SpringBoot接收參數(shù)所有方式總結(jié)
這篇文章主要介紹了SpringBoot接收參數(shù)所有方式總結(jié),文中通過代碼示例和圖文結(jié)合的方式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-07-07Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(37)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你2021-07-07關(guān)于springboot整合swagger問題及解決方法
這篇文章主要介紹了關(guān)于springboot整合swagger問題及解決方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04Springboot AOP對指定敏感字段數(shù)據(jù)加密存儲(chǔ)的實(shí)現(xiàn)
本篇文章主要介紹了利用Springboot+AOP對指定的敏感數(shù)據(jù)進(jìn)行加密存儲(chǔ)以及對數(shù)據(jù)中加密的數(shù)據(jù)的解密的方法,代碼詳細(xì),具有一定的價(jià)值,感興趣的小伙伴可以了解一下2021-11-11Java?Git?Commit?Message使用規(guī)范
這篇文章主要介紹了Java?Git?Commit?Message使用規(guī)范,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下,希望對你的學(xué)習(xí)有所幫助2022-08-08Springboot視頻接口報(bào)大量的ClientAbortException找不到原因的解決
本文主要介紹了Springboot視頻接口報(bào)大量的ClientAbortException找不到原因的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08