最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中Lombok的@Builder注解注意事項(xiàng)

 更新時間:2023年12月08日 09:04:09   作者:GeorgiaStar  
這篇文章主要介紹了Java中Lombok的@Builder注解注意事項(xiàng),使用Lombok也會造成很多問題,尤其@Builder 有個很大的坑,已經(jīng)見過好幾次由于使用@Builder注解導(dǎo)致默認(rèn)值失效的問題,如果測試時沒有在意這個問題,就很容易引發(fā)線上問題,需要的朋友可以參考下

前言

現(xiàn)在很多程序員都習(xí)慣使用Lombok來使代碼更加 “簡潔”。

但是使用Lombok也會造成很多問題,尤其@Builder 有個很大的坑,已經(jīng)見過好幾次由于使用@Builder注解導(dǎo)致默認(rèn)值失效的問題,如果測試時沒有在意這個問題,就很容易引發(fā)線上問題。

問題復(fù)現(xiàn)

我們隨便定義一個類Config,對其中兩個屬性設(shè)置默認(rèn)值。

import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class Config {
    private boolean isOpen = true;
    private String name;
    private int value = 20;
}
public class LombokDemo {
    public static void main(String[] args) {
        Config config = Config.builder().name("test").build();
        System.out.println(config);
    }
}

借助Builder模式創(chuàng)建Config類實(shí)例時,僅設(shè)置name屬性,然后打印出實(shí)例

public class LombokDemo {
    public static void main(String[] args) {
        Config config = Config.builder().name("test").build();
        System.out.println(config);
    }
}

輸出結(jié)果如下。

Config(isOpen=false, name=test, value=0)

我們?yōu)閕sOpen及value屬性設(shè)置的默認(rèn)值失效了。

原因分析

想了解為什么會這樣,我們只需要查看使用Lombok的注解后的Config類的 class文件長啥樣就明白了。

@Builder通過Lombok的注解處理器,在編譯時會自動生成一個靜態(tài)內(nèi)部類,這個內(nèi)部類就是所謂的builder類,它包含了和被注解的類中的屬性一一對應(yīng)的setter方法,并且在build()方法中返回一個被注解的類的對象。

這個builder類的代碼實(shí)現(xiàn)是通過Lombok生成的,所以我們不需要手動編寫。

public class Config {
    private boolean isOpen = true;
    private String name;
    private int value = 20;
    Config(boolean isOpen, String name, int value) {
        this.isOpen = isOpen;
        this.name = name;
        this.value = value;
    }
    public static ConfigBuilder builder() {
        return new ConfigBuilder();
    }
    public boolean isOpen() {
        return this.isOpen;
    }
    public String getName() {
        return this.name;
    }
    public int getValue() {
        return this.value;
    }
    public void setOpen(boolean isOpen) {
        this.isOpen = isOpen;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setValue(int value) {
        this.value = value;
    }
    public boolean equals(Object o) {
      // 省略
    }
    protected boolean canEqual(Object other) {
        return other instanceof Config;
    }
    public int hashCode() {
        // 省略
    }
    public String toString() {
        return "Config(isOpen=" + this.isOpen() + ", name=" + this.getName() + ", value=" + this.getValue() + ")";
    }
    public static class ConfigBuilder {
        private boolean isOpen;
        private String name;
        private int value;
        ConfigBuilder() {
        }
        public ConfigBuilder isOpen(boolean isOpen) {
            this.isOpen = isOpen;
            return this;
        }
        public ConfigBuilder name(String name) {
            this.name = name;
            return this;
        }
        public ConfigBuilder value(int value) {
            this.value = value;
            return this;
        }
        public Config build() {
            return new Config(this.isOpen, this.name, this.value);
        }
        public String toString() {
            return "Config.ConfigBuilder(isOpen=" + this.isOpen + ", name=" + this.name + ", value=" + this.value + ")";
        }
    }
}

可以看到,ConfigBuilder中isOpen和value屬性并沒有使用我們想要設(shè)置的默認(rèn)值。

調(diào)用build方法時, ConfigBuilder會調(diào)用全參的構(gòu)造方法來構(gòu)造Config 對象。

解決方法

使用@Builder.Default注解來標(biāo)識帶默認(rèn)值的屬性

import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class SomeConfig {
	@Builder.Default
    private boolean isOpen = true;
    private String name;
    @Builder.Default
    private int value = 20;
}

修改后輸出結(jié)果如下

Config(isOpen=true, name=test, value=20)

為什么加了@Builder.Default注解就能解決問題呢,看一下編譯后的class文件就明白了

public class Config {
    private boolean isOpen;
    private String name;
    private int value;
    private static boolean $default$isOpen() {
        return true;
    }
    private static int $default$value() {
        return 20;
    }
    Config(boolean isOpen, String name, int value) {
        this.isOpen = isOpen;
        this.name = name;
        this.value = value;
    }
    public static ConfigBuilder builder() {
        return new ConfigBuilder();
    }
    public boolean isOpen() {
        return this.isOpen;
    }
    public String getName() {
        return this.name;
    }
    public int getValue() {
        return this.value;
    }
    public void setOpen(boolean isOpen) {
        this.isOpen = isOpen;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setValue(int value) {
        this.value = value;
    }
    public boolean equals(Object o) {
       // 省略
    }
    protected boolean canEqual(Object other) {
        return other instanceof Config;
    }
    public int hashCode() {
       // 省略
    }
    public String toString() {
        boolean var10000 = this.isOpen();
        return "Config(isOpen=" + var10000 + ", name=" + this.getName() + ", value=" + this.getValue() + ")";
    }
    public static class ConfigBuilder {
        private boolean isOpen$set;
        private boolean isOpen$value;
        private String name;
        private boolean value$set;
        private int value$value;
        ConfigBuilder() {
        }
        public ConfigBuilder isOpen(boolean isOpen) {
            this.isOpen$value = isOpen;
            this.isOpen$set = true;
            return this;
        }
        public ConfigBuilder name(String name) {
            this.name = name;
            return this;
        }
        public ConfigBuilder value(int value) {
            this.value$value = value;
            this.value$set = true;
            return this;
        }
        public Config build() {
            boolean isOpen$value = this.isOpen$value;
            if (!this.isOpen$set) {
                isOpen$value = Config.$default$isOpen();
            }
            int value$value = this.value$value;
            if (!this.value$set) {
                value$value = Config.$default$value();
            }
            return new Config(isOpen$value, this.name, value$value);
        }
        public String toString() {
            return "Config.ConfigBuilder(isOpen$value=" + this.isOpen$value + ", name=" + this.name + ", value$value=" + this.value$value + ")";
        }
    }
}

每個設(shè)置默認(rèn)值的屬性都會在Builder中加上是否設(shè)置的標(biāo)記,如果沒有主動設(shè)置值,則調(diào)用Config中的默認(rèn)值的靜態(tài)方法進(jìn)行賦值,然后再調(diào)用Config全參構(gòu)造方法構(gòu)造該對象。

使用@Builder注解的缺點(diǎn)

  1. 如果在類上使用了@Builder 注解,那么你需要手動添加一個無參構(gòu)造函數(shù),否則有些序列化框架需要通過newInstance構(gòu)造對象時會報錯。
  2. 如果在類上使用了@Builder注解,就不能再在構(gòu)造函數(shù)或方法上使用 @Builder注解,否則會導(dǎo)致重復(fù)生成構(gòu)造器類
  3. 如果在類上使用了@Builder 注解,想給某個屬性設(shè)置一個默認(rèn)值,還需要在屬性上使用@Builder.Default 注解,否則默認(rèn)值會被忽略。
  4. 如果想讓子類繼承父類的屬性,那么你需要在子類的全參構(gòu)造函數(shù)上使用 @Builder注解,并且在父類上使用@AllArgsConstructor注解,否則子類的構(gòu)造器類不會包含父類的屬性

到此這篇關(guān)于Java中Lombok的@Builder注解注意事項(xiàng)的文章就介紹到這了,更多相關(guān)Lombok的@Builder注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文詳解JAVA中InputStreamReader流

    一文詳解JAVA中InputStreamReader流

    本文主要介紹了一文詳解JAVA中InputStreamReader流,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • linux下idea、pycharm等輸入中文拼音時滿3個字母后無法繼續(xù)拼音輸入的問題

    linux下idea、pycharm等輸入中文拼音時滿3個字母后無法繼續(xù)拼音輸入的問題

    這篇文章主要介紹了linux下idea、pycharm等輸入中文拼音時滿3個字母后無法繼續(xù)拼音輸入的問題,本文通過圖文并茂的形式給大家分享解決方法,需要的朋友可以參考下
    2021-04-04
  • Spring MVC無法正確接收From表單參數(shù)的解決方案

    Spring MVC無法正確接收From表單參數(shù)的解決方案

    文章描述了在處理Spring Boot中的表單提交時遇到的JSON解析錯誤,并通過分析代碼和HTTP請求的contentType,解釋了錯誤的原因,主要內(nèi)容包括了ajax請求中contentType的設(shè)置以及@RequestBody注解的作用,最后給出了具體的解決辦法
    2025-12-12
  • Java?數(shù)據(jù)結(jié)構(gòu)與算法系列精講之棧

    Java?數(shù)據(jù)結(jié)構(gòu)與算法系列精講之棧

    棧(stack)又名堆棧,它是一種運(yùn)算受限的線性表。限定僅在表尾進(jìn)行插入和刪除操作的線性表。這一端被稱為棧頂,相對地,把另一端稱為棧底,棧是基礎(chǔ)中的基礎(chǔ),如果你還沒掌握透徹就來接著往下看吧
    2022-02-02
  • SpringBoot + Mybatis增刪改查實(shí)戰(zhàn)記錄

    SpringBoot + Mybatis增刪改查實(shí)戰(zhàn)記錄

    這篇文章主要給大家介紹了關(guān)于SpringBoot + Mybatis增刪改查的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Spring Data JPA 建立表的聯(lián)合主鍵

    Spring Data JPA 建立表的聯(lián)合主鍵

    這篇文章主要介紹了Spring Data JPA 建立表的聯(lián)合主鍵。本文詳細(xì)的介紹了2種方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-04-04
  • SpringBoot實(shí)現(xiàn)Redis多數(shù)據(jù)庫切換(多數(shù)據(jù)源配置)

    SpringBoot實(shí)現(xiàn)Redis多數(shù)據(jù)庫切換(多數(shù)據(jù)源配置)

    在實(shí)際開發(fā)中,隨著業(yè)務(wù)復(fù)雜度提升,我們常常會遇到?Redis?需要按不同業(yè)務(wù)模塊分庫管理的需求,本文將以?Spring?Boot?為例,教大家如何優(yōu)雅地實(shí)現(xiàn)?Redis?多數(shù)據(jù)庫(多數(shù)據(jù)源)切換,需要的可以了解下
    2025-07-07
  • Spring Boot如何防止重復(fù)提交

    Spring Boot如何防止重復(fù)提交

    這篇文章主要為大家詳細(xì)介紹了Spring Boot如何防止重復(fù)提交,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • SpringAOP實(shí)現(xiàn)日志收集管理功能(步驟詳解)

    SpringAOP實(shí)現(xiàn)日志收集管理功能(步驟詳解)

    這篇文章主要介紹了SpringAOP實(shí)現(xiàn)日志收集管理功能,本文分步驟通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03
  • Java關(guān)鍵字this(動力節(jié)點(diǎn)Java學(xué)院整理)

    Java關(guān)鍵字this(動力節(jié)點(diǎn)Java學(xué)院整理)

    java中的this隨處可見,用法也多。通常情況下理解this關(guān)鍵字還是很容易的,但是在我初學(xué)的時候,有一個疑問卻一直不能很清晰的理解,現(xiàn)在慢慢的理解了,下面通過本文給大家記錄下,有需要的朋友參考下
    2017-03-03

最新評論

临海市| 万年县| 高尔夫| 晴隆县| 年辖:市辖区| 绍兴市| 方正县| 永德县| 崇信县| 屯留县| 牟定县| 靖边县| 包头市| 卢湾区| 云南省| 泸西县| 溧水县| 即墨市| 宝兴县| 祁东县| 吴堡县| 崇州市| 汝州市| 新兴县| 宁夏| 米林县| 宁远县| 新野县| 馆陶县| 稻城县| 柳江县| 河南省| 巴东县| 宣威市| 资阳市| 柯坪县| 平顺县| 隆德县| 荃湾区| 琼结县| 武功县|