java使用反射給對象屬性賦值的兩種方法
前言
最近項目中遇到一個問題,就是能實現(xiàn)一個類將以后的多語都進行轉換的通用方法,根據(jù)這個需求,決定使用反射實現(xiàn),根據(jù)反射給對象屬性設置屬性值,下面是使用反射實現(xiàn)對對象屬性值進行設置的方法
方法1:這里使用了Field的set方的 Field 屬性,然后設置可見性,然后設置了一個值,最后打印
// 給變量賦值 給object對象的某個字段賦值
f.set(object, value);
//拿到了Field類的實例后就可以調用其中的方法了
//方法:get(Object obj) 返回指定對象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());
}
}
由此可見,使用反射我們能給很容易的給各個屬性進行設置,即使是private的屬性我們也能很輕松的設置屬性值,下面利用這個demo例子,就設置了我們的最初的功能。
總結:
也就是說,第一種方法,沒有調用屬性的set方法就完成了賦值,
但是第二種方法,是通過調用屬性的set方法來完成賦值。
所以,如果想在程序中改變程序的屬性的值的同時還想做一些額外的事情,可以將這些事情寫到set方法中并使用第二種方法
public class MultiLangContentUtil {
/**
* 從PO查詢數(shù)據(jù)賦值到DTO
* 注意!!這里的多語字段根據(jù)
* 簡體中文的變量名 英文名和繁體名需要根據(jù)規(guī)則進行 指定
* 規(guī)則如下
* 英文名=簡體中文名2
* 繁體名=簡體中文名3
*
* @param targetPO 數(shù)據(jù)庫中查詢出的數(shù)據(jù)
* @param targetDTO 將要轉換的對象DTO
* @param targetMultiName 需要展示的多語字段
* @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進行展示
Field declaredFieldDTO = targetDTOClass.getDeclaredField(targetMultiName);
declaredFieldDTO.setAccessible(true);
switch (locale) {
case ZH_CN:
//獲取PO的值
Field declaredFieldPO = targetPOClass.getDeclaredField(targetMultiName);
//獲取DTO對象
declaredFieldPO.setAccessible(true);
//對DTO根據(jù)PO進行設置
declaredFieldDTO.set(targetDTO, declaredFieldPO.get(targetPO));
break;
case EN_US:
//獲取PO的值
Field declaredFieldPO2 = targetPOClass.getDeclaredField(targetMultiName + 2);
//獲取DTO對象
declaredFieldPO2.setAccessible(true);
//對DTO根據(jù)PO進行設置
declaredFieldDTO.set(targetDTO, declaredFieldPO2.get(targetPO));
break;
case ZH_TW:
//獲取PO的值
Field declaredFieldPO3 = targetPOClass.getDeclaredField(targetMultiName + 3);
//獲取DTO對象
declaredFieldPO3.setAccessible(true);
//對DTO根據(jù)PO進行設置
declaredFieldDTO.set(targetDTO, declaredFieldPO3.get(targetPO));
break;
default:
break;
}
//防止沒有抽取多語的情況下沒有參照返回,默認情況下設置中文
if (StringUtils.isBlank((String) declaredFieldDTO.get(targetDTO))) {
//獲取PO的值
Field declaredFieldPO = targetPOClass.getDeclaredField(targetMultiName);
//獲取DTO對象
declaredFieldPO.setAccessible(true);
//對DTO根據(jù)PO進行設置
declaredFieldDTO.set(targetDTO, declaredFieldPO.get(targetPO));
}
} catch (NoSuchFieldException e) {
log.error("查詢當前字段--->{}不存在{},", targetMultiName, e);
} catch (IllegalAccessException e) {
log.error("查詢字段--->{}多語時發(fā)生非法狀態(tài)異常{},", targetMultiName, e);
} catch (Exception e) {
log.error("查詢字段{}多語時發(fā)生錯誤{},", targetMultiName, e);
} catch (Throwable throwable) {
log.error("查詢多語言字段{}發(fā)生未知錯誤{}", targetMultiName, ThrowableUtil.stackTraceToString(throwable));
}
}
/**
* 更新多語字段
*
* @param targetDTO 需要轉換的字段
* @param targetPO 數(shù)據(jù)庫PO
* @param fieldName 多語字段
* @param MultiLangSize 多語字段的數(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("更新當前字段--->{}不存在{},", fieldName, e);
} catch (IllegalAccessException e) {
log.error("更新字段--->{}多語時發(fā)生非法狀態(tài)異常{},", fieldName, e);
} catch (Exception e) {
log.error("更新字段{}多語時發(fā)生錯誤{},", fieldName, e);
} catch (Throwable throwable) {
log.error("更新多語言字段{}發(fā)生未知錯誤{}", fieldName, ThrowableUtil.stackTraceToString(throwable));
}
}
/**
* 獲取本地的語言,默認中文
* en_US 英文
* zh_CN 簡體中文
* zh_TW 繁體中文
*
* @return
*/
public static final String getLocale() {
String locale = InvocationInfoProxy.getLocale();
return StringUtils.isEmpty(locale) ? "zh_CN" : locale;
}
}這個工具類的核心思想就是
- 使用Field的get方法獲取屬性值
- Field的set方法設置屬性
// 給變量賦值 給object對象的某個字段賦值
f.set(object, value);
//拿到了Field類的實例后就可以調用其中的方法了
//方法:get(Object obj) 返回指定對象obj上此 Field 表示的字段的值
到此這篇關于java使用反射給對象屬性賦值的文章就介紹到這了,更多相關java反射給對象屬性賦值內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
解決springboot與springcloud版本兼容問題(附版本兼容表)
在基于spring boot搭建spring cloud時,創(chuàng)建eureka后啟動服務發(fā)生報錯,本文給大家介紹了解決springboot與springcloud版本兼容問題的幾種方案,需要的朋友可以參考下2024-02-02
利用Kotlin + Spring Boot實現(xiàn)后端開發(fā)
這篇文章主要給大家介紹了關于利用Kotlin + Spring Boot實現(xiàn)后端開發(fā)的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2018-11-11
詳解Spring緩存注解@Cacheable,@CachePut , @CacheEvict使用
這篇文章主要介紹了詳解Spring緩存注解@Cacheable,@CachePut , @CacheEvict使用,非常具有實用價值,需要的朋友可以參考下2017-05-05
springboot使用之多個filter的執(zhí)行順序以及配置方式
這篇文章主要介紹了springboot使用之多個filter的執(zhí)行順序以及配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08
spring boot與spring mvc的區(qū)別及功能介紹
這篇文章主要介紹了spring boot與spring mvc的區(qū)別是什么以及spring boot和spring mvc功能介紹,感興趣的朋友一起看看吧2018-02-02

