Java對象中轉換空值的欄位

来源:https://www.cnblogs.com/kzyuan/archive/2023/06/09/17469931.html
-Advertisement-
Play Games

數組可以通過索引快速訪問和操作元素,在許多場景下仍然是非常有用的,但如果需要動態調整大小或保存不同類型的元素,則可以考慮使用集合類來代替數組。集合類還提供了一系列增加、刪除、修改和查找元素的方法。集合框架中還提供了多種優化和封裝好的實現類,通過使用合適的集合類可以更高效地組織和操作數據。 ...


在後端返回數據給前端時,公司的框架會把值為null的數據去掉,方便前端取值。

如:Person對象為:{name:"浩二", age:24, weight:null, height:114},那返回給前端的就為{name:"浩二", age:24, height:114}。

如果這個時候有個需求:

  Integer類型的欄位為null給-1

  Long類型的欄位為null給-1L

  String類型的欄位為null給""(空字元串)

  對象類型的欄位為null給new對象,

不能直接動框架,因此需要手動轉化。

 

代碼寫死轉換

這種是最簡單的方式,顧名思義,寫死代碼的方式一個一個欄位來轉換

示例

轉換對象 ConvertNullFiledInfo

@Data
public class ConvertNullFiledInfo {
​
    private Integer intNum;
​
    private Long longNum;
​
    private String str;
​
    private ConvertNullFiledInfo info;
​
}

轉換代碼

@Service
public class ConvertNullFiledService {
​
    /**
     * 寫死代碼的方式一個一個欄位來轉換
     * @param info
     * @return
     */
    public ConvertNullFiledInfo convertFunction01(ConvertNullFiledInfo info) {
        info.setIntNum(info.getIntNum() == null ? -1 : info.getIntNum());
        info.setLongNum(info.getLongNum() == null ? -1L : info.getLongNum());
        info.setStr(info.getStr() == null ? "" : info.getStr());
        info.setInfo(info.getInfo() == null ? new ConvertNullFiledInfo() : info.getInfo());
        return info;
    }
    
}

測試代碼

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
​
​
@SpringBootTest
@RunWith(SpringRunner.class)
public class ConvertNullFiledServiceTest {
​
    @Autowired
    private ConvertNullFiledService convertNullFiledService;
​
    @Test
    public void convertFunction01() {
        // str和info欄位給null
        ConvertNullFiledInfo info = createConvertNullFiledInfo(1, 1L, null, null);
        ConvertNullFiledInfo result = convertNullFiledService.convertFunction01(info);
        System.out.println(result);
    }
​
    /**
     * 自定義欄位創建ConvertNullFiledInfo
     * @param intNum
     * @param longNum
     * @param str
     * @param info
     * @return
     */
    private ConvertNullFiledInfo createConvertNullFiledInfo(Integer intNum, Long longNum, String str, ConvertNullFiledInfo info) {
        ConvertNullFiledInfo result = new ConvertNullFiledInfo();
        result.setIntNum(intNum);
        result.setLongNum(longNum);
        result.setStr(str);
        result.setInfo(info);
        return result;
    }
    
}

運行結果

可以看到是正常轉換了的

問題點

這樣寫雖然簡單方便,但是如果有非常多的對象需要轉換,就會有許多重覆代碼;

而且如果欄位有修改(類型、名稱、被刪除、新增),就需要在去轉換方法中修改,因此可以用更好的方式。

 

遍歷Filed轉換

所有對象都有Class<T>類,而Class有getDeclaredFields()方法,能獲取到所有欄位(filed),

因此可以使用這種方式來轉換。

示例

轉換代碼

/**
     * 遍歷field的方式一個一個欄位來轉換
     * @param info
     * @return
     */
    public ConvertNullFiledInfo convertByField(ConvertNullFiledInfo info) {
        try {
            Field[] fields = info.getClass().getDeclaredFields();
            for (Field field : fields) {
                // 設置可訪問私有變數
                field.setAccessible(true);
                // 獲取當前欄位值
                Object value = field.get(info);
                // value不為空就跳過
                if (value != null) {
                    continue;
                }
                // 獲取當前欄位類型
                Class<?> type = field.getType();
                if (type == Integer.class) {
                    // Integer類型就設置為-1
                    field.set(info, -1);
                } else if (type == Long.class) {
                    // Long類型就設置為-1L
                    field.set(info, -1L);
                } else if (type == String.class) {
                    // String類型就設置為“”
                    field.set(info, "");
                } else if (type == ConvertNullFiledInfo.class) {
                    // ConvertNullFiledInfo類型就設置為新對象
                    field.set(info, new ConvertNullFiledInfo());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return info;
    }

測試代碼

@Test
public void convertByField() {
    // str和info欄位給null
    ConvertNullFiledInfo info = createConvertNullFiledInfo(1, 1L, null, null);
    ConvertNullFiledInfo result = convertNullFiledService.convertByField(info);
    System.out.println(result);
}

運行結果

可以看到也是成功轉換了

問題點

這種寫法仍然存在問題,可以看到方法的傳參和返回值都是固定類型為ConvertNullFiledInfo,

並且在遍歷field的時候,也有if判斷是寫定的ConvertNullFiledInfo,

因此也在一定程度上寫死了代碼

優化

為了避免寫死的情況,可以使用泛型來寫

轉換代碼

@Service
public class ConvertNullFiledService<T> {
    
    /**
     * 使用泛型,遍歷field的方式一個一個欄位來轉換
     * @param object
     * @return
     */
    public T convertByFieldGeneric(T object) {
        try {
            Field[] fields = object.getClass().getDeclaredFields();
            for (Field field : fields) {
                // 設置可訪問私有變數
                field.setAccessible(true);
                // 獲取當前欄位值
                Object value = field.get(object);
                // value不為空就跳過
                if (value != null) {
                    continue;
                }
                // 獲取當前欄位類型
                Class<?> type = field.getType();
                if (type == Integer.class) {
                    // Integer類型就設置為-1
                    field.set(object, -1);
                } else if (type == Long.class) {
                    // Long類型就設置為-1L
                    field.set(object, -1L);
                } else if (type == String.class) {
                    // String類型就設置為“”
                    field.set(object, "");
                } else if (type == object.getClass()) {
                    // T類型就設置為新對象
                    Object newObj = object.getClass().newInstance();
                    field.set(object, newObj);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }
}

測試代碼

@Test
public void convertByFieldGeneric() {
    // 全部欄位給null
    ConvertNullFiledInfo info = createConvertNullFiledInfo(null, null, null, null);
    ConvertNullFiledInfo result = (ConvertNullFiledInfo) convertNullFiledService.convertByFieldGeneric(info);
    System.out.println(result);
}

運行結果

成功轉換

 
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Map
    基於electron25+vite4+vue3仿製chatgpt客戶端聊天模板ElectronChatGPT。 electron-chatgpt 使用最新桌面端技術Electron25.x結合Vite4.x全家桶技術開發跨端模仿ChatGPT智能聊天程式模板。支持經典+分欄兩種佈局、暗黑+明亮主題模 ...
  • 在應用層下的文件操作只需要調用微軟應用層下的`API`函數及`C庫`標準函數即可,而如果在內核中讀寫文件則應用層的API顯然是無法被使用的,內核層需要使用內核專有API,某些應用層下的API只需要增加Zw開頭即可在內核中使用,例如本章要講解的文件與目錄操作相關函數,多數ARK反內核工具都具有對文件的... ...
  • # ImageIO的應用 # 一、關於IO流 在講imageio之前,我們先來複習一下IO流的使用。 這裡我建立一個Java類,用來實現讀取文檔中的內容,並且能夠識別換行,話不多說,上代碼: ```java package com.Evan.demo; import java.io.Buffered ...
  • 某日二師兄參加XXX科技公司的C++工程師開發崗位第10面: > 面試官:瞭解`sizeof`操作符嗎? > > 二師兄:略微瞭解(不就是求大小的嘛。。) > > 面試官:請講以下如何使用`sizeof`? > > 二師兄:`sizeof`主要是求變數或者類型的大小。直接使用`sizeof(type ...
  • # Rust - 介面設計建議之靈活(flexible) ## 靈活(flexible) ### 代碼的契約(Contract) - 你寫的代碼包含契約 - 契約: - 要求:代碼使用的限制 - 承諾:代碼使用的保證 - 設計介面時(經驗法則): - 避免施加不必要的限制,只做能夠兌現的承諾 - 增 ...
  • # JavaWeb ## 基本概念 web開發: - web:網頁的意思 - 靜態web:提供的數據資源不會發生改變 - 動態web:數據是不斷變化的,現代網站幾乎都是動態網站技術棧: Servlet/JSP:基於java,主推B/S架構,可以 ​ 承載高併發,語法類似ASP ​ ASP:微軟,國內 ...
  • 背景 要集成chatGpt參考我上一篇文章即可。但是,如果要實現官網一樣的效果,逐字輸出,難度就提升了不少了。經過在官網的研究發現它應該是採用了SSE技術,這是一種最新的HTTP交互技術。SSE(Server-Sent Events):通俗解釋起來就是一種基於HTTP的,以流的形式由服務端持續向客戶 ...
  • 在Java中,創建線程是一項非常重要的任務。線程是一種輕量級的子進程,可以並行執行,使得程式的執行效率得到提高。Java提供了多種方式來創建線程,但許多人都認為Java有三種創建線程的方式,它們分別是繼承Thread類、實現Runnable介面和使用線程池。但是,你們知道嗎?其實在創建線程的過程中,... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...