java使用反射給對(duì)象屬性賦值的兩種方法
前言
最近項(xiàng)目中遇到一個(gè)問題,就是能實(shí)現(xiàn)一個(gè)類將以后的多語(yǔ)都進(jìn)行轉(zhuǎn)換的通用方法,根據(jù)這個(gè)需求,決定使用反射實(shí)現(xiàn),根據(jù)反射給對(duì)象屬性設(shè)置屬性值,下面是使用反射實(shí)現(xiàn)對(duì)對(duì)象屬性值進(jìn)行設(shè)置的方法
方法1:這里使用了Field的set方的 Field 屬性,然后設(shè)置可見性,然后設(shè)置了一個(gè)值,最后打印
// 給變量賦值 給object對(duì)象的某個(gè)字段賦值
f.set(object, value);
//拿到了Field類的實(shí)例后就可以調(diào)用其中的方法了
//方法:get(Object obj) 返回指定對(duì)象obj上此 Field 表示的字段的值
package com.example.reflectiondemo;
import java.lang.reflect.Field;
/**
* @program my-project-model
* @description:
* @author: lee
* @create: 2023/01/04 19:52
*/
public class ReflectMain {
private String readOnly;
public String getReadOnly() {
return readOnly;
}
public void setReadOnly(String readOnly) {
System.out.println("set");
this.readOnly = readOnly;
}
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
ReflectMain t = new ReflectMain();
Field f = t.getClass().getDeclaredField("readOnly");
f.setAccessible(true);
f.set(t, "test");
System.out.println(t.getReadOnly());
}
}方法2:使用invoke方法
package com.example.reflectiondemo;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @program my-project-model
* @description:
* @author: lee
* @create: 2023/01/04 19:52
*/
public class ReflectMain {
private String readOnly;
public String getReadOnly() {
return readOnly;
}
public void setReadOnly(String readOnly) {
System.out.println("set");
this.readOnly = readOnly;
}
// public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
// ReflectMain t = new ReflectMain();
// Field f = t.getClass().getDeclaredField("readOnly");
// f.setAccessible(true);
// f.set(t, "test");
// System.out.println(t.getReadOnly());
//
// }
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ReflectMain t = new ReflectMain();
Method setReadOnly = t.getClass().getMethod("setReadOnly", String.class);
String s = "test2";
setReadOnly.invoke(t, s);
System.out.println(t.getReadOnly());
}
}
由此可見,使用反射我們能給很容易的給各個(gè)屬性進(jìn)行設(shè)置,即使是private的屬性我們也能很輕松的設(shè)置屬性值,下面利用這個(gè)demo例子,就設(shè)置了我們的最初的功能。
總結(jié):
也就是說(shuō),第一種方法,沒有調(diào)用屬性的set方法就完成了賦值,
但是第二種方法,是通過(guò)調(diào)用屬性的set方法來(lái)完成賦值。
所以,如果想在程序中改變程序的屬性的值的同時(shí)還想做一些額外的事情,可以將這些事情寫到set方法中并使用第二種方法
public class MultiLangContentUtil {
/**
* 從PO查詢數(shù)據(jù)賦值到DTO
* 注意?。∵@里的多語(yǔ)字段根據(jù)
* 簡(jiǎn)體中文的變量名 英文名和繁體名需要根據(jù)規(guī)則進(jìn)行 指定
* 規(guī)則如下
* 英文名=簡(jiǎn)體中文名2
* 繁體名=簡(jiǎn)體中文名3
*
* @param targetPO 數(shù)據(jù)庫(kù)中查詢出的數(shù)據(jù)
* @param targetDTO 將要轉(zhuǎn)換的對(duì)象DTO
* @param targetMultiName 需要展示的多語(yǔ)字段
* @throws NoSuchFieldException
* @throws IllegalAccessException
*/
public static void setMultiLangDTOName(Object targetPO, Object targetDTO, String targetMultiName) {
try {
String locale = MultiLangContentUtil.getLocale();
Class<?> targetDTOClass = targetDTO.getClass();
Class<?> targetPOClass = targetPO.getClass();
//這里是將targetMultiName進(jìn)行展示
Field declaredFieldDTO = targetDTOClass.getDeclaredField(targetMultiName);
declaredFieldDTO.setAccessible(true);
switch (locale) {
case ZH_CN:
//獲取PO的值
Field declaredFieldPO = targetPOClass.getDeclaredField(targetMultiName);
//獲取DTO對(duì)象
declaredFieldPO.setAccessible(true);
//對(duì)DTO根據(jù)PO進(jìn)行設(shè)置
declaredFieldDTO.set(targetDTO, declaredFieldPO.get(targetPO));
break;
case EN_US:
//獲取PO的值
Field declaredFieldPO2 = targetPOClass.getDeclaredField(targetMultiName + 2);
//獲取DTO對(duì)象
declaredFieldPO2.setAccessible(true);
//對(duì)DTO根據(jù)PO進(jìn)行設(shè)置
declaredFieldDTO.set(targetDTO, declaredFieldPO2.get(targetPO));
break;
case ZH_TW:
//獲取PO的值
Field declaredFieldPO3 = targetPOClass.getDeclaredField(targetMultiName + 3);
//獲取DTO對(duì)象
declaredFieldPO3.setAccessible(true);
//對(duì)DTO根據(jù)PO進(jìn)行設(shè)置
declaredFieldDTO.set(targetDTO, declaredFieldPO3.get(targetPO));
break;
default:
break;
}
//防止沒有抽取多語(yǔ)的情況下沒有參照返回,默認(rèn)情況下設(shè)置中文
if (StringUtils.isBlank((String) declaredFieldDTO.get(targetDTO))) {
//獲取PO的值
Field declaredFieldPO = targetPOClass.getDeclaredField(targetMultiName);
//獲取DTO對(duì)象
declaredFieldPO.setAccessible(true);
//對(duì)DTO根據(jù)PO進(jìn)行設(shè)置
declaredFieldDTO.set(targetDTO, declaredFieldPO.get(targetPO));
}
} catch (NoSuchFieldException e) {
log.error("查詢當(dāng)前字段--->{}不存在{},", targetMultiName, e);
} catch (IllegalAccessException e) {
log.error("查詢字段--->{}多語(yǔ)時(shí)發(fā)生非法狀態(tài)異常{},", targetMultiName, e);
} catch (Exception e) {
log.error("查詢字段{}多語(yǔ)時(shí)發(fā)生錯(cuò)誤{},", targetMultiName, e);
} catch (Throwable throwable) {
log.error("查詢多語(yǔ)言字段{}發(fā)生未知錯(cuò)誤{}", targetMultiName, ThrowableUtil.stackTraceToString(throwable));
}
}
/**
* 更新多語(yǔ)字段
*
* @param targetDTO 需要轉(zhuǎn)換的字段
* @param targetPO 數(shù)據(jù)庫(kù)PO
* @param fieldName 多語(yǔ)字段
* @param MultiLangSize 多語(yǔ)字段的數(shù)量
*/
public static void updateMultiLang(Object targetDTO, Object targetPO, String fieldName, Integer MultiLangSize) {
try {
Class<?> targetDTOClass = targetDTO.getClass();
Class<?> targetPOClass = targetPO.getClass();
Field dtoClassField = targetDTOClass.getDeclaredField(fieldName);
dtoClassField.setAccessible(true);
if (StringUtils.isNotBlank((String) dtoClassField.get(targetDTO))) {
Field poClassField = targetPOClass.getDeclaredField(fieldName);
poClassField.setAccessible(true);
poClassField.set(targetPO, dtoClassField.get(targetDTO));
}
for (int i = 2; i <= MultiLangSize; i++) {
Field dtoClassField2 = targetDTOClass.getDeclaredField(fieldName + i);
dtoClassField2.setAccessible(true);
if (StringUtils.isNotBlank((String) dtoClassField2.get(targetDTO))) {
Field poClassField2 = targetPOClass.getDeclaredField(fieldName + i);
poClassField2.setAccessible(true);
poClassField2.set(targetPO, dtoClassField2.get(targetDTO));
}
}
} catch (NoSuchFieldException e) {
log.error("更新當(dāng)前字段--->{}不存在{},", fieldName, e);
} catch (IllegalAccessException e) {
log.error("更新字段--->{}多語(yǔ)時(shí)發(fā)生非法狀態(tài)異常{},", fieldName, e);
} catch (Exception e) {
log.error("更新字段{}多語(yǔ)時(shí)發(fā)生錯(cuò)誤{},", fieldName, e);
} catch (Throwable throwable) {
log.error("更新多語(yǔ)言字段{}發(fā)生未知錯(cuò)誤{}", fieldName, ThrowableUtil.stackTraceToString(throwable));
}
}
/**
* 獲取本地的語(yǔ)言,默認(rèn)中文
* en_US 英文
* zh_CN 簡(jiǎn)體中文
* zh_TW 繁體中文
*
* @return
*/
public static final String getLocale() {
String locale = InvocationInfoProxy.getLocale();
return StringUtils.isEmpty(locale) ? "zh_CN" : locale;
}
}這個(gè)工具類的核心思想就是
- 使用Field的get方法獲取屬性值
- Field的set方法設(shè)置屬性
// 給變量賦值 給object對(duì)象的某個(gè)字段賦值
f.set(object, value);
//拿到了Field類的實(shí)例后就可以調(diào)用其中的方法了
//方法:get(Object obj) 返回指定對(duì)象obj上此 Field 表示的字段的值
到此這篇關(guān)于java使用反射給對(duì)象屬性賦值的文章就介紹到這了,更多相關(guān)java反射給對(duì)象屬性賦值內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決springboot與springcloud版本兼容問題(附版本兼容表)
在基于spring boot搭建spring cloud時(shí),創(chuàng)建eureka后啟動(dòng)服務(wù)發(fā)生報(bào)錯(cuò),本文給大家介紹了解決springboot與springcloud版本兼容問題的幾種方案,需要的朋友可以參考下2024-02-02
Java設(shè)計(jì)實(shí)現(xiàn)一個(gè)針對(duì)各種類型的緩存
這篇文章主要為大家詳細(xì)介紹了Java如何設(shè)計(jì)實(shí)現(xiàn)一個(gè)針對(duì)各種類型的緩存,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下2023-11-11
利用Kotlin + Spring Boot實(shí)現(xiàn)后端開發(fā)
這篇文章主要給大家介紹了關(guān)于利用Kotlin + Spring Boot實(shí)現(xiàn)后端開發(fā)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-11-11
詳解Spring緩存注解@Cacheable,@CachePut , @CacheEvict使用
這篇文章主要介紹了詳解Spring緩存注解@Cacheable,@CachePut , @CacheEvict使用,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-05-05
springboot使用之多個(gè)filter的執(zhí)行順序以及配置方式
這篇文章主要介紹了springboot使用之多個(gè)filter的執(zhí)行順序以及配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
SpringMVC上傳文件的三種實(shí)現(xiàn)方式
本篇文章主要介紹了SpringMVC上傳文件的三種實(shí)現(xiàn)方式,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12
spring boot與spring mvc的區(qū)別及功能介紹
這篇文章主要介紹了spring boot與spring mvc的區(qū)別是什么以及spring boot和spring mvc功能介紹,感興趣的朋友一起看看吧2018-02-02

