Java反射機制調用對象的方法 —— 將一個對象的屬性值賦值給另一個對象的屬性


 

模擬一個場景:

眾所周知,EasyExcel導出Excel文檔是依賴於注解完成的,在實體類需要導出的屬性上面加上注解,導出的時候會自動識別該屬性。

假如我們現在需要導出用戶的信息,又不想污染原本的實體類,又要過濾掉password這個屬性。那么我們可以另外創建一個實體類,不包含password屬性。然后我們將查到的用戶信息,賦值給新創建的對象即可。

賦值這一步是比較繁瑣的,我們需要寫循環,然后判斷,然后賦值。等將來需要導出管理員信息的時候我們又要寫循環,然后判斷,然后賦值、、、

怎么能寫一個共用的方法去幫我們做循環、判斷、賦值這些事呢?源對象類型不確定,目標對象類型不確定。

於是,反射機制來了。它來了,它來了,它哼着小曲走來了、、、

通過 Java 的反射機制,程序員可以更深入地控制程序的運行過程。例如,在程序運行時由用戶輸入一個類名,然后動態獲取該類擁有的構造、屬性和方法,甚至調用任意類的任意方法。

Java 反射機制主要提供了以下功能,這些功能都位於 java.lang.reflect包下。

  • 在運行時判斷任意一個對象所屬的類。

  • 在運行時構造任意一個類的對象。

  • 在運行時判斷任意一個類所具有的成員變量和方法。

  • 在運行時調用任意一個對象的方法。

  • 生成動態代理。

開發環境

請參照: 基於SpringBoot構建分模塊項目

創建對象UserOne、UserTwo

UserOne為與數據庫表對應的實體類,UserTwo為即將要通過EasyExcel導出的對象

package com.wayne.common.entity;
​
/**
 * @author Wayne
 * @date 2019/6/5
 */
public class UserOne {
​
    private Integer id;
​
    private String username;
​
    private String password;
​
   // Getter and Setter 、、、
}

 

package com.wayne.common.dto;
​
/**
 * @author Wayne
 * @date 2019/6/5
 */
public class UserTwo {
​
    private Integer id;
​
    private String username;
​
    // Getter and Setter 、、、
}

編寫基於反射的工具類

通過反射創建對象、調用方法

package com.wayne.common.utils;
​
import com.google.common.collect.Lists;
import com.wayne.common.exception.CopyPropertyException;
​
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
​
/**
 * @author Wayne
 * @date 2019/6/5
 */
public class BaseUtil {
​
    /**
     * 將一個集合中對象的值拷貝到另一個對象,屬性相同即賦值
     * @param source 源數據,將此對象數據取出
     * @param tClass 目標對象,將取出的數據賦值到該對象中
     * @param <T> 源數據類型
     * @param <E> 目標數據類型
     * @return 被賦值后的目標對象集合
     * @throws CopyPropertyException 自定義異常,通過反射創建對象或調用方法時拋出的異常
     */
    public static <T, E> List<E> copyProperties(List<T> source, Class<E> tClass) throws CopyPropertyException {
​
        // 判斷傳入源數據是否為空,如果空,則拋自定義異常
        if(null == source) {
            throw new CopyPropertyException("數據源為空");
        }
​
        // 創建一個集合,用於存儲目標對象,全部數據抓換完成后,將該集合返回
        List<E> targetList = Lists.newArrayList();
​
        // 循環取到單個源對象
        for(T t : source) {
            // 獲取源對象的類的詳情信息
            Class<?> sClass = t.getClass();
            // 獲取源對象的所有屬性
            Field[] sFields = sClass.getDeclaredFields();
            // 獲取目標對象的所有屬性
            Field[] tFields = tClass.getDeclaredFields();
​
            E target;
            try {
                // 通過類的詳情信息,創建目標對象 這一步等同於UserTwo target = new UserTwo();
                target = tClass.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
                throw new CopyPropertyException("目標對象創建失敗");
            }
​
            // 循環取到源對象的單個屬性
            for(Field sField : sFields) {
                // 循環取到目標對象的單個屬性
                for(Field tField : tFields) {
​
                    // 判斷源對象的屬性名、屬性類型是否和目標對象的屬性名、屬性類型一致
                    if(sField.getName().equals(tField.getName()) && sField.getGenericType().equals(tField.getGenericType())) {
​
                        try {
                            // 獲取源對象的屬性名,將屬性名首字母大寫,拼接如:getUsername、getId的字符串
                            String sName = sField.getName();
                            char[] sChars = sName.toCharArray();
                            sChars[0] -= 32;
                            String sMethodName = "get" + String.valueOf(sChars);
                            // 獲得屬性的get方法
                            Method sMethod = sClass.getMethod(sMethodName);
                            // 調用get方法
                            Object sFieldValue = sMethod.invoke(t);
​
                            // 獲取目標對象的屬性名,將屬性名首字母大寫,拼接如:setUsername、setId的字符串
                            String tName = tField.getName();
                            char[] tChars = tName.toCharArray();
                            tChars[0] -= 32;
                            String tMethodName = "set" + String.valueOf(tChars);
                            // 獲得屬性的set方法
                            Method tMethod = tClass.getMethod(tMethodName, tField.getType());
                            // 調用方法,並將源對象get方法返回值作為參數傳入
                            tMethod.invoke(target, sFieldValue);
​
                            break;
                        } catch (Exception e) {
                            e.printStackTrace();
                            throw new CopyPropertyException("轉換失敗,請檢查屬性類型是否匹配");
                        }
                    }
                }
            }
            // 將通過反射創建的目標對象放入集合中
            targetList.add(target);
        }
        // 返回集合
        return targetList;
    }
}

 

測試結果

預留占位

開發怎能不留擴展字段 (¬_¬)…

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



猜您在找 用反射的形式將一個對象屬性值賦值給另一個對象,省略點get/set方法的冗余代碼 關於反射的基本應用--將一個對象中的所有屬性值賦值給另一個對象 java 對象屬性復制,將一個對象的屬性值賦值給另一個對象, 屬性名需要相同 將一個多重對象的所有值賦值給另一個對象 C#利用反射實現兩個類的對象之間相同屬性的值的復制,一個對象的屬性復制給另一個對性的屬性 vue對象深拷貝(避免對象賦值,改變一個對象的值,另一個對象也變化) Java的反射機制-動態調用對象的方法 按要求編寫Java應用程序。 (1)創建一個叫做People的類: 屬性:姓名、年齡、性別、身高 行為:說話、計算加法、改名 編寫能為所有屬性賦值的構造方法; (2)創建主類: 創建一個對象:名叫“張三”,性別“男”,年齡18歲,身高1.80; 讓該對象調用成員方法: 說出“你好!” 計算23+45的值 將名字改為“李四” 按要求編寫Java應用程序。 (1)創建一個叫做People的類: 屬性:姓名、年齡、性別、身高 行為:說話、計算加法、改名 編寫能為所有屬性賦值的構造方法; (2)創建主類: 創建一個對象:名叫“張三”,性別“男”,年齡18歲,身高1.80; 讓該對象調用成員方法: 說出“你好!” 計算23+45的值 將名字改為“李四” 10.按要求編寫Java應用程序。 (1)創建一個叫做People的類: 屬性:姓名、年齡、性別、身高 行為:說話、計算加法、改名 編寫能為所有屬性賦值的構造方法; (2)創建主類: 創建一個對象:名叫“張三”,性別“男”,年齡18歲,身高1.80; 讓該對象調用成員方法: 說出“你好!” 計算23+45的值 將名字改為“李四”
 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM