日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

使用@Builder導致的無法創建無參構造方法

作者:搏·夢 更新時間: 2022-05-25 編程語言

文章目錄

  • 1. 前言
  • 2. 先說結論
  • 3. 演示
  • 4. 解決方法
    • 1. 在實體類上再加上@AllArgsConstructor即可
    • 2. 手寫個無參構造函數并加上@Tolerate
    • 3. 手寫有參無參構造方法

1. 前言

  1. 在創建實體類的時候,有時候參數過于多,如果使用有參數的構造函數,實在看起來不是很優雅,一般都會想使用@Builder構建者模式來進行創建對象,不僅僅優雅,而且還方便。
  2. 當偶然機會發現,如果使用了@Builder,該實體類會失去無參構造方法
  3. 具體現象如下:
    當不加任何注解的時候,完成正常:
    在這里插入圖片描述
    當加了@Builder的時候,則會直接出現下面的錯誤,提示沒有無參的構造函數:
    在這里插入圖片描述

2. 先說結論

  1. 由于沒有時間深入查看@Builder的源碼,但是可以從編譯之后的字節碼得出結論:
    1. 實體類使用了@Builder,會有全參構造函數,沒有默認無參構造函數,即無法使用默認無參構造函數。
    2. 解決方法:
      1. 在實體類上同時加上:@Builder、@AllArgsConstructor、@NoArgsConstructor

      2. 手寫全部有參構造方法,以及 無參構造方法

      3. 手寫個默認無參構造方法,并加上@Tolerate

        @Builder
        public class demoBuilderEntry {
            private String name;
            private String sex;
        
            @Tolerate
            public demoBuilderEntry() {
            }
        }
        

3. 演示

  1. 若不知道怎么查看java反編譯字節碼內容,可以看一下:
    Java 如何進行反編譯生成.java文件(javap、jad下載安裝使用)

  2. 當實體類不加任何東西:

    public class demoBuilderEntry {
        private String name;
        private String sex;
    }
    

    可以看見是默認有無參構造函數

    public class demoBuilderEntry {
    
        public demoBuilderEntry() {
        }
    
        private String name;
        private String sex;
    }
    
  3. 當實體類加上@Builder注解:

    @Builder
    public class demoBuilderEntry {
        private String name;
        private String sex;
    }
    

    可以看出:無參構造函數已不存在,只剩全參構造函數

    public class demoBuilderEntry {
        public static class demoBuilderEntryBuilder {
    
            public demoBuilderEntryBuilder name(String name) {
                this.name = name;
                return this;
            }
    
            public demoBuilderEntryBuilder sex(String sex) {
                this.sex = sex;
                return this;
            }
    
            public demoBuilderEntry build() {
                return new demoBuilderEntry(name, sex);
            }
    
            public String toString() {
                return (new StringBuilder()).append("demoBuilderEntry.demoBuilderEntryBuilder(name=").append(name).append(", sex=").append(sex).append(")").toString();
            }
    
            private String name;
            private String sex;
    
            demoBuilderEntryBuilder() {
            }
        }
    
        demoBuilderEntry(String name, String sex) {
            this.name = name;
            this.sex = sex;
        }
    
        public static demoBuilderEntryBuilder builder() {
            return new demoBuilderEntryBuilder();
        }
    
        private String name;
        private String sex;
    }
    
    

    因此,如下圖,一定會報錯:
    在這里插入圖片描述

    有人會說:沒有無參怎么了,也沒有什么事情,反正需要構造。
    但像spring這種,我們可以從配置文件中注入屬性,如@ConfigurationProperties,它們的做法是先創建該類對象,使用無參構造函數,然后再調用set方法,此時,你沒有默認無參構造方法,必然會失敗,畢竟連對象都沒有創建成功。
    具體失敗案例可以看:實體類使用@Builder,導致@ConfigurationProperties注入屬性失敗

  4. 如果需要無參構造函數,那就手動添加,在實體類上,再加上@NoArgsConstructor也無效。
    根據下圖可以看見,似乎沒有報錯
    在這里插入圖片描述

    當運行的時候,則報錯如下:與實際參數列表不符,顯然是無法通過加@NoArgsConstructor創建默認無參構造函數
    在這里插入圖片描述

4. 解決方法

1. 在實體類上再加上@AllArgsConstructor即可

  1. 根據下圖查看,似乎也沒有問題:
    在這里插入圖片描述

  2. 點擊運行,查看結果的時候,居然可以運行成功如下:
    在這里插入圖片描述

  3. 反手我們去看一下反編譯:

    
    public class demoBuilderEntry {
        public static class demoBuilderEntryBuilder {
            // builder 的代碼省略,沒有粘出來
        }
        
        public static void main(String args[]) {
            System.out.println(new demoBuilderEntry());
        }
    
        public static demoBuilderEntryBuilder builder() {
            return new demoBuilderEntryBuilder();
        }
    
        public demoBuilderEntry(String name, String sex) {
            this.name = name;
            this.sex = sex;
        }
    	// 無參構造函數有了
        public demoBuilderEntry() {
        }
    
        private String name;
        private String sex;
    }
    
    

2. 手寫個無參構造函數并加上@Tolerate

  1. @Tolerate:中文:容許,通俗來說,被該注解加上的方法,讓lombok容許它們存在。

    /**
     * Put on any method or constructor to make lombok pretend it doesn't exist,
     * i.e., to generate a method which would otherwise be skipped due to possible conflicts.
     */
    @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Tolerate {
    }
    
  2. 測試:
    在這里插入圖片描述

3. 手寫有參無參構造方法

  1. 這種方法是最簡單粗暴的,但是代碼可能會沒有那么簡潔:
    在這里插入圖片描述

原文鏈接:https://blog.csdn.net/xueyijin/article/details/124391228

欄目分類
最近更新