欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中使用 @Builder 注解的簡(jiǎn)單示例

 更新時(shí)間:2025年07月22日 14:58:05   作者:程序猿進(jìn)階  
@Builder簡(jiǎn)化構(gòu)建但存在復(fù)雜性,需配合其他注解,導(dǎo)致可變性、抽象類型處理難題,鏈?zhǔn)骄幊谭亲罴褜?shí)踐,適合長(zhǎng)期對(duì)象,避免與@Data混用,改用@Getter更佳,本文給大家介紹到底應(yīng)不應(yīng)該使用@Builder的相關(guān)知識(shí),感興趣的朋友一起看看吧

大多數(shù)同學(xué)使用 @Builder 無(wú)非就是為了鏈?zhǔn)骄幊?,然?@Builder 并不是鏈?zhǔn)骄幊痰淖罴褜?shí)踐,它會(huì)額外創(chuàng)建內(nèi)部類,存在繼承關(guān)系時(shí)還需要使用 @SuperBuilder 注解,設(shè)置默認(rèn)值時(shí)也需要額外的 @Builder.Default 去設(shè)置默認(rèn)值,無(wú)疑增加了很多不必要的復(fù)雜度。

一、案例

@Builder 注解是 Lombok 庫(kù)中的一個(gè)注解,用于簡(jiǎn)化 Java 對(duì)象的構(gòu)建過(guò)程。它通過(guò)生成一個(gè)構(gòu)建器模式(Builder Pattern)來(lái)創(chuàng)建對(duì)象,使得代碼更簡(jiǎn)潔和易于維護(hù)。以下是一個(gè)使用 @Builder 注解的簡(jiǎn)單示例:

假設(shè)我們有一個(gè) User 類:

import lombok.Builder;
import lombok.ToString;
@Builder
@ToString
public class User {
    private String name;
    private int age;
    private String email;
}

在例子中,@Builder 注解會(huì)為 User 類生成一個(gè)靜態(tài)內(nèi)部類 UserBuilder,用于構(gòu)建 User 對(duì)象。@ToString 注解則是為了方便輸出對(duì)象信息。

使用 @Builder 注解生成的構(gòu)建器來(lái)創(chuàng)建 User 對(duì)象:

public class Main {
    public static void main(String[] args) {
        User user = User.builder()
                        .name("John Doe")
                        .age(30)
                        .email("johndoe@example.com")
                        .build();
        System.out.println(user);
    }
}

在這個(gè)示例中,通過(guò) User.builder() 方法獲取一個(gè) UserBuilder 實(shí)例,然后通過(guò)鏈?zhǔn)秸{(diào)用設(shè)置各個(gè)屬性,最后調(diào)用 build() 方法創(chuàng)建 User 對(duì)象。

這種方式的優(yōu)點(diǎn)是可以靈活地設(shè)置對(duì)象的屬性,并且不需要?jiǎng)?chuàng)建多個(gè)構(gòu)造函數(shù)來(lái)滿足不同的初始化需求。特別是在屬性較多的類中,使用 @Builder 可以顯著提高代碼的可讀性和可維護(hù)性。

二、不足之處

@Builder 生成的構(gòu)造器不是完美的,它不能區(qū)分哪些參數(shù)是必須的,哪些是可選的。如果沒(méi)有提供必須的參數(shù),構(gòu)造器可能會(huì)創(chuàng)建出不完整或者不合法的對(duì)象。

假設(shè)我們有一個(gè) Order 類,其中 orderId 是必須的,而 description 是可選的:

import lombok.Builder;
import lombok.ToString;
@Builder
@ToString
public class Order {
    private String orderId;  // 必須的參數(shù)
    private String description;  // 可選的參數(shù)
}

在使用 @Builder 構(gòu)建 Order 對(duì)象時(shí),可能會(huì)出現(xiàn)這樣的情況:

public class Main {
    public static void main(String[] args) {
        // 忘記設(shè)置必須的 orderId
        Order order = Order.builder()
                           .description("This is an optional description")
                           .build();
        System.out.println(order);
    }
}

在這個(gè)示例中,由于 orderId 是一個(gè)必須的參數(shù),但在構(gòu)建 Order 對(duì)象時(shí)沒(méi)有提供 orderId,導(dǎo)致生成的對(duì)象可能不合法或不完整。

很多人 喜歡 @Builder 和 @Data 搭配使用,導(dǎo)致生成的構(gòu)造器是可變的,它允許使用 setter 方法修改構(gòu)造器的狀態(tài)。這違反了構(gòu)造器模式的原則,構(gòu)造器應(yīng)該是不可變的,一旦創(chuàng)建就不能被修改。

如果非要使用 @Builder ,那么不要用 @Data ,要用 @Getter。相對(duì)來(lái)說(shuō),反而 @Accessors 的行為更符合這個(gè)要求。

@Builder 生成的構(gòu)造器不適合用于短暫的對(duì)象,它會(huì)增加代碼的復(fù)雜度和冗余。構(gòu)造器模式更適合用于生命周期較長(zhǎng)、有多種變體的對(duì)象。

實(shí)際使用中經(jīng)常發(fā)現(xiàn) @Builder 濫用的情況,有些僅僅一兩個(gè)屬性的類也都要用 @Builder,真的沒(méi)必要用,直接用全參的構(gòu)造方法都比這更簡(jiǎn)潔。

@Builder 生成的構(gòu)造器不能處理抽象類型的參數(shù),它只能接受具體類型的對(duì)象。這限制了構(gòu)造器的靈活性和擴(kuò)展性,不能根據(jù)不同的需求創(chuàng)建不同風(fēng)格的對(duì)象。

假設(shè)我們有一個(gè)抽象的 Vehicle 類和一個(gè)具體的 Car 類:

public abstract class Vehicle {
    private String brand;
    public Vehicle(String brand) {
        this.brand = brand;
    }
    public String getBrand() {
        return brand;
    }
}
public class Car extends Vehicle {
    private int numberOfDoors;
    public Car(String brand, int numberOfDoors) {
        super(brand);
        this.numberOfDoors = numberOfDoors;
    }
    public int getNumberOfDoors() {
        return numberOfDoors;
    }
}

現(xiàn)在,我們嘗試使用 @Builder 來(lái)創(chuàng)建一個(gè)包含 Vehicle 類型參數(shù)的 Garage 類:

import lombok.Builder;
import lombok.ToString;
@Builder
@ToString
public class Garage {
    private Vehicle vehicle;  // 抽象類型參數(shù)
}

在使用 @Builder 創(chuàng)建 Garage 對(duì)象時(shí),我們會(huì)遇到問(wèn)題,因?yàn)?Vehicle 是一個(gè)抽象類,無(wú)法直接實(shí)例化:

public class Main {
    public static void main(String[] args) {
        // 這段代碼會(huì)有問(wèn)題,因?yàn)?Vehicle 是抽象的,不能直接實(shí)例化
        Garage garage = Garage.builder()
                              .vehicle(new Vehicle("Generic Brand") {})  // 錯(cuò)誤:不能實(shí)例化抽象類
                              .build();
        System.out.println(garage);
    }
}

解決方案:使用具體類型:在構(gòu)建器中使用具體類型的對(duì)象,而不是抽象類型。例如,直接使用 Car 類

public class Main {
    public static void main(String[] args) {
        Car car = new Car("Toyota", 4);
        Garage garage = Garage.builder()
                              .vehicle(car)
                              .build();
        System.out.println(garage);
    }
}

繼承關(guān)系時(shí),子類需要使用 @SuperBuilder。對(duì)象繼承后,子類的 Builder 因?yàn)闃?gòu)造函數(shù)的問(wèn)題,使用不當(dāng)大概率會(huì)報(bào)錯(cuò),并且無(wú)法設(shè)置父類的屬性,還需要使用 @SuperBuilder 來(lái)解決問(wèn)題。

假設(shè)我們有一個(gè)父類 Vehicle 和一個(gè)子類 Car,并希望通過(guò)構(gòu)建器來(lái)設(shè)置它們的屬性:通過(guò) @SuperBuilder,我們可以在子類的構(gòu)建器中設(shè)置父類的屬性:

public class Main {
    public static void main(String[] args) {
        Car car = Car.builder()
                     .brand("Toyota")      // 設(shè)置父類的屬性
                     .model("Corolla")     // 設(shè)置父類的屬性
                     .numberOfDoors(4)     // 設(shè)置子類的屬性
                     .build();
        System.out.println("Brand: " + car.getBrand());
        System.out.println("Model: " + car.getModel());
        System.out.println("Number of Doors: " + car.getNumberOfDoors());
    }
}

@SuperBuilder 注解:它是 @Builder 的增強(qiáng)版本,專門(mén)用于處理繼承關(guān)系。使用 @SuperBuilder 可以在子類的構(gòu)建器中訪問(wèn)和設(shè)置父類的屬性。

final 關(guān)鍵字:在這個(gè)示例中,屬性被聲明為 final,確保它們?cè)趯?duì)象構(gòu)建后不可變。

構(gòu)建器鏈:@SuperBuilder 允許在子類的構(gòu)建器中調(diào)用父類的構(gòu)建器方法,從而設(shè)置父類的屬性。

設(shè)置默認(rèn)值需要使用 @Builder.Default。很容易因?yàn)閷?duì)此不了解,導(dǎo)致默認(rèn)值不符合預(yù)期導(dǎo)致出現(xiàn) BUG。

import lombok.Builder;
import lombok.Getter;
import lombok.ToString;
@Getter
@Builder
@ToString
public class User {
    private final String username;
    private final String email;
    @Builder.Default
    private final boolean active = true;  // 默認(rèn)值
    @Builder.Default
    private final int loginAttempts = 0;  // 默認(rèn)值
}
public class Main {
    public static void main(String[] args) {
        // 使用構(gòu)建器創(chuàng)建對(duì)象,并未顯式設(shè)置 active 和 loginAttempts
        User user = User.builder()
                        .username("john_doe")
                        .email("john.doe@example.com")
                        .build();
        System.out.println(user);
        // 顯式設(shè)置 active 和 loginAttempts
        User anotherUser = User.builder()
                               .username("jane_doe")
                               .email("jane.doe@example.com")
                               .active(false)
                               .loginAttempts(3)
                               .build();
        System.out.println(anotherUser);
    }
}

到此這篇關(guān)于Java中使用 @Builder 注解的簡(jiǎn)單示例的文章就介紹到這了,更多相關(guān)java使用 @Builder 注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java程序員自己的圖片轉(zhuǎn)文字OCR識(shí)圖工具分享

    java程序員自己的圖片轉(zhuǎn)文字OCR識(shí)圖工具分享

    這篇文章主要介紹了java程序員自己的圖片轉(zhuǎn)文字OCR識(shí)圖工具,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • Java簡(jiǎn)單數(shù)組排序(冒泡法)

    Java簡(jiǎn)單數(shù)組排序(冒泡法)

    這篇文章主要介紹了Java簡(jiǎn)單數(shù)組排序,實(shí)例分析了基于冒泡法實(shí)現(xiàn)數(shù)組排序的相關(guān)技巧,簡(jiǎn)單實(shí)用,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-10-10
  • application.yml文件中如何開(kāi)啟mybatis自動(dòng)駝峰映射

    application.yml文件中如何開(kāi)啟mybatis自動(dòng)駝峰映射

    這篇文章主要介紹了application.yml文件中開(kāi)啟mybatis自動(dòng)駝峰映射的方法,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • 關(guān)于垃圾回收的三色標(biāo)記算法的使用解讀

    關(guān)于垃圾回收的三色標(biāo)記算法的使用解讀

    這篇文章主要介紹了關(guān)于垃圾回收的三色標(biāo)記算法的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • SpringBoot靜態(tài)資源與首頁(yè)配置實(shí)現(xiàn)原理深入分析

    SpringBoot靜態(tài)資源與首頁(yè)配置實(shí)現(xiàn)原理深入分析

    最近在做SpringBoot項(xiàng)目的時(shí)候遇到了“白頁(yè)”問(wèn)題,通過(guò)查資料對(duì)SpringBoot訪問(wèn)靜態(tài)資源做了總結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2022-10-10
  • Java NIO 文件通道 FileChannel 用法及原理

    Java NIO 文件通道 FileChannel 用法及原理

    這篇文章主要介紹了Java NIO 文件通道 FileChannel 用法和原理,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • SpringData @Query和@Modifying注解原理解析

    SpringData @Query和@Modifying注解原理解析

    這篇文章主要介紹了SpringData @Query和@Modifying注解原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Mybatis動(dòng)態(tài)查詢字段及表名的實(shí)現(xiàn)

    Mybatis動(dòng)態(tài)查詢字段及表名的實(shí)現(xiàn)

    本文主要介紹了Mybatis動(dòng)態(tài)查詢字段及表名的實(shí)現(xiàn),通過(guò)靈活運(yùn)用Mybatis提供的動(dòng)態(tài)SQL功能,我們可以構(gòu)建更加靈活、高效的查詢語(yǔ)句,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2024-01-01
  • Java多線程中Lock鎖的使用小結(jié)

    Java多線程中Lock鎖的使用小結(jié)

    這篇文章主要介紹了Java多線程中Lock鎖的使用小結(jié),本節(jié)主要講了它的基本使用,大家可以舉一反三,試試什么條件下會(huì)導(dǎo)致死鎖,需要的朋友可以參考下
    2022-06-06
  • java實(shí)現(xiàn)的順時(shí)針/逆時(shí)針打印矩陣操作示例

    java實(shí)現(xiàn)的順時(shí)針/逆時(shí)針打印矩陣操作示例

    這篇文章主要介紹了java實(shí)現(xiàn)的順時(shí)針/逆時(shí)針打印矩陣操作,涉及java基于數(shù)組的矩陣存儲(chǔ)、遍歷、打印輸出等相關(guān)操作技巧,需要的朋友可以參考下
    2019-12-12

最新評(píng)論