Java中使用 @Builder 注解的簡單示例
大多數(shù)同學(xué)使用 @Builder 無非就是為了鏈?zhǔn)骄幊?,然?@Builder 并不是鏈?zhǔn)骄幊痰淖罴褜嵺`,它會額外創(chuàng)建內(nèi)部類,存在繼承關(guān)系時還需要使用 @SuperBuilder 注解,設(shè)置默認(rèn)值時也需要額外的 @Builder.Default 去設(shè)置默認(rèn)值,無疑增加了很多不必要的復(fù)雜度。
一、案例
@Builder 注解是 Lombok 庫中的一個注解,用于簡化 Java 對象的構(gòu)建過程。它通過生成一個構(gòu)建器模式(Builder Pattern)來創(chuàng)建對象,使得代碼更簡潔和易于維護(hù)。以下是一個使用 @Builder 注解的簡單示例:
假設(shè)我們有一個 User 類:
import lombok.Builder;
import lombok.ToString;
@Builder
@ToString
public class User {
private String name;
private int age;
private String email;
}在例子中,@Builder 注解會為 User 類生成一個靜態(tài)內(nèi)部類 UserBuilder,用于構(gòu)建 User 對象。@ToString 注解則是為了方便輸出對象信息。
使用 @Builder 注解生成的構(gòu)建器來創(chuàng)建 User 對象:
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);
}
}在這個示例中,通過 User.builder() 方法獲取一個 UserBuilder 實例,然后通過鏈?zhǔn)秸{(diào)用設(shè)置各個屬性,最后調(diào)用 build() 方法創(chuàng)建 User 對象。
這種方式的優(yōu)點是可以靈活地設(shè)置對象的屬性,并且不需要創(chuàng)建多個構(gòu)造函數(shù)來滿足不同的初始化需求。特別是在屬性較多的類中,使用 @Builder 可以顯著提高代碼的可讀性和可維護(hù)性。
二、不足之處
@Builder 生成的構(gòu)造器不是完美的,它不能區(qū)分哪些參數(shù)是必須的,哪些是可選的。如果沒有提供必須的參數(shù),構(gòu)造器可能會創(chuàng)建出不完整或者不合法的對象。
假設(shè)我們有一個 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 對象時,可能會出現(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);
}
}在這個示例中,由于 orderId 是一個必須的參數(shù),但在構(gòu)建 Order 對象時沒有提供 orderId,導(dǎo)致生成的對象可能不合法或不完整。
很多人 喜歡 @Builder 和 @Data 搭配使用,導(dǎo)致生成的構(gòu)造器是可變的,它允許使用 setter 方法修改構(gòu)造器的狀態(tài)。這違反了構(gòu)造器模式的原則,構(gòu)造器應(yīng)該是不可變的,一旦創(chuàng)建就不能被修改。
如果非要使用 @Builder ,那么不要用 @Data ,要用 @Getter。相對來說,反而 @Accessors 的行為更符合這個要求。
@Builder 生成的構(gòu)造器不適合用于短暫的對象,它會增加代碼的復(fù)雜度和冗余。構(gòu)造器模式更適合用于生命周期較長、有多種變體的對象。
實際使用中經(jīng)常發(fā)現(xiàn) @Builder 濫用的情況,有些僅僅一兩個屬性的類也都要用 @Builder,真的沒必要用,直接用全參的構(gòu)造方法都比這更簡潔。
@Builder 生成的構(gòu)造器不能處理抽象類型的參數(shù),它只能接受具體類型的對象。這限制了構(gòu)造器的靈活性和擴展性,不能根據(jù)不同的需求創(chuàng)建不同風(fēng)格的對象。
假設(shè)我們有一個抽象的 Vehicle 類和一個具體的 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 來創(chuàng)建一個包含 Vehicle 類型參數(shù)的 Garage 類:
import lombok.Builder;
import lombok.ToString;
@Builder
@ToString
public class Garage {
private Vehicle vehicle; // 抽象類型參數(shù)
}在使用 @Builder 創(chuàng)建 Garage 對象時,我們會遇到問題,因為 Vehicle 是一個抽象類,無法直接實例化:
public class Main {
public static void main(String[] args) {
// 這段代碼會有問題,因為 Vehicle 是抽象的,不能直接實例化
Garage garage = Garage.builder()
.vehicle(new Vehicle("Generic Brand") {}) // 錯誤:不能實例化抽象類
.build();
System.out.println(garage);
}
}解決方案:使用具體類型:在構(gòu)建器中使用具體類型的對象,而不是抽象類型。例如,直接使用 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)系時,子類需要使用 @SuperBuilder。對象繼承后,子類的 Builder 因為構(gòu)造函數(shù)的問題,使用不當(dāng)大概率會報錯,并且無法設(shè)置父類的屬性,還需要使用 @SuperBuilder 來解決問題。
假設(shè)我們有一個父類 Vehicle 和一個子類 Car,并希望通過構(gòu)建器來設(shè)置它們的屬性:通過 @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 的增強版本,專門用于處理繼承關(guān)系。使用 @SuperBuilder 可以在子類的構(gòu)建器中訪問和設(shè)置父類的屬性。
final 關(guān)鍵字:在這個示例中,屬性被聲明為 final,確保它們在對象構(gòu)建后不可變。
構(gòu)建器鏈:@SuperBuilder 允許在子類的構(gòu)建器中調(diào)用父類的構(gòu)建器方法,從而設(shè)置父類的屬性。
設(shè)置默認(rèn)值需要使用 @Builder.Default。很容易因為對此不了解,導(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)建對象,并未顯式設(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 注解的簡單示例的文章就介紹到這了,更多相關(guān)java使用 @Builder 注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringCloud超詳細(xì)講解微服務(wù)網(wǎng)關(guān)Zuul基礎(chǔ)
這篇文章主要介紹了SpringCloud?Zuul微服務(wù)網(wǎng)關(guān),負(fù)載均衡,熔斷和限流,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-10-10
spring boot + jpa + kotlin入門實例詳解
這篇文章主要介紹了spring boot + jpa + kotlin入門實例詳解 ,需要的朋友可以參考下2017-07-07
實例解決Java異常之OutOfMemoryError的問題
在本篇文章中,我們給大家分享了關(guān)于解決Java異常之OutOfMemoryError的問題的方法,有此需要的朋友們學(xué)習(xí)下。2019-02-02
SpringBoot集成Redis實現(xiàn)訂單超時管理的詳細(xì)步驟
文章描述了如何使用Redis來處理超時支付訂單,包括引入依賴、配置連接、定義實體類、實現(xiàn)服務(wù)和監(jiān)聽器等步驟,文章討論了優(yōu)化方案、注意事項以及Redis的性能和可靠性問題,感興趣的朋友跟隨小編一起看看吧2026-03-03
java 抓取網(wǎng)頁內(nèi)容實現(xiàn)代碼
這篇文章主要介紹了java 抓取網(wǎng)頁內(nèi)容實現(xiàn)代碼,需要的朋友可以參考下2014-02-02
SpringBoot HikariCP連接池監(jiān)控實現(xiàn)方案
文章介紹了五種監(jiān)控SpringBoot應(yīng)用程序中HikariCP連接池狀態(tài)和性能的工具和技術(shù),包括SpringBootActuator、Micrometer、Prometheus+Grafana、HikariCP自帶的Metrics以及NewRelic/Datadog等第三方服務(wù),每種方法都有其特點和配置步驟2025-01-01
Java實現(xiàn)利用圖片或視頻生成GIF并發(fā)送微信
這篇文章主要為大家詳細(xì)介紹了Java語言如何利用圖片或視頻實現(xiàn)生成GIF并發(fā)送微信的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下2022-11-11

