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

Java中的@Builder注解問題詳解

 更新時(shí)間:2023年10月02日 10:10:58   作者:Archie_java  
這篇文章主要介紹了Java中的@Builder注解詳解,@Builder 注解的其中一個(gè)大坑會(huì)導(dǎo)致默認(rèn)值失效,這是使用此注解出現(xiàn)的一個(gè)問題,總的來說,不推薦再使用 @Builder 注解,接下來講重點(diǎn)介紹其原因和替代方案,需要的朋友可以參考下

一、前言

 @Builder 注解的其中一個(gè)大坑會(huì)導(dǎo)致默認(rèn)值失效!

@Builder 的問題還不止一個(gè), @Builder 會(huì)讓人誤以為是遵循構(gòu)建器模式,實(shí)則不然,后面會(huì)介紹。

總的來說,不推薦再使用 @Builder 注解,接下來講重點(diǎn)介紹其原因和替代方案。

二、場(chǎng)景復(fù)現(xiàn)

2.1 如果不使用 @Builder

類定義:

package io.gitrebase.demo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class APIResponse<T> {
    private T payload;
    private Status status;
}

使用示例:

package io.gitrebase.demo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@Slf4j
@RestControllerAdvice(assignableTypes = io.gitrebase.demo.RestApplication.class)
public class ApplicationExceptionHandler {
    @ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
    public APIResponse handleException(Exception exception) {
        log.error("Unhandled Exception", exception);
        Status status = new Status();
        status.setResponseCode("RESPONSE_CODE_IDENTIFIER");
        status.setDescription("Bla Bla Bla");
        APIResponse response = new APIResponse();
        response.setStatus(status);
        return response;
    }
}

2.2 使用 @Builder

類定義:

package io.gitrebase.demo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class APIResponse<T> {
    private T payload;
    private Status status;
}

使用示例:

package io.gitrebase.demo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@Slf4j
@RestControllerAdvice(basePackageClasses = io.gitrebase.demo.RestApplication.class)
public class ApplicationExceptionHandler {
    @ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
    public APIResponse handleException(Exception exception) {
        log.error("Unhandled Exception", exception);
        return APIResponse.builder().status(Status.builder()
                .responseCode("RESPONSE_CODE_IDENTIFIER")
                .description("Bla Bla Bla")
                .build())
                .build();
    }
}

三、為什么不推薦使用 @Builder ?

  • @Builder 會(huì)生成一個(gè)不完美的構(gòu)建器,它不能區(qū)分哪些參數(shù)是必須的,哪些是可選的。這可能會(huì)導(dǎo)致構(gòu)建對(duì)象時(shí)出現(xiàn)錯(cuò)誤或不一致的情況。
  • 很多人習(xí)慣于將 @Builder 和 @Data 一起使用使用會(huì)生成一個(gè)可變的構(gòu)建器,它有 setter 方法可以修改構(gòu)建器的狀態(tài)。這違反了構(gòu)建器模式的原則,即構(gòu)建器應(yīng)該是不可變的,一旦創(chuàng)建就不能修改。
  • @Builder 會(huì)生成一個(gè)具體類型的構(gòu)建器,它不能適應(yīng)不同類型的參數(shù)。這限制了構(gòu)建器模式的優(yōu)勢(shì),即可以根據(jù)不同的抽象類型創(chuàng)建不同風(fēng)格的對(duì)象。
  • @Builder 的使用場(chǎng)景很有限,它只適合那些有很多參數(shù)且大部分是可選的對(duì)象。對(duì)于那些只想實(shí)現(xiàn)一個(gè)流式風(fēng)格的對(duì)象創(chuàng)建,@Builder 并不是一個(gè)好的選擇。

四、替代方案

4.1 首推: @Accessor

類的定義:

package io.gitrebase.demo;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class APIResponse<T> {
    private T payload;
    private Status status;
}

編譯后的類:

package io.gitrebase.demo;
import lombok.experimental.Accessors;
@Accessors(chain = true)
public class APIResponse<T> {
    private T payload;
    private Status status;
    public T getPayload() {
        return this.payload;
    }
    public APIResponse<T> setPayload(T payload) {
        this.payload = payload;
        return this;
    }
    public Status getStatus() {
        return this.status;
    }
    public APIResponse<T> setStatus(Status status) {
        this.status = status;
        return this;
    }
}

使用示例:

package io.gitrebase.demo;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@Slf4j
@RestControllerAdvice(basePackageClasses = io.gitrebase.demo.RestApplication.class)
public class ApplicationExceptionHandler {
    @ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
    public APIResponse handleException(Exception exception) {
        log.error("Unhandled Exception", exception);
        var status = new Status().setResponseCode("RESPONSE_CODE_IDENTIFIER").setDescription("Bla Bla Bla");
        return new APIResponse().setStatus(status);
    }
}

此外,該注解還支持一些高級(jí)方法:

/**
 * A container for settings for the generation of getters and setters.
 * <p>
 * Complete documentation is found at <a  rel="external nofollow" >the project lombok features page for &#64;Accessors</a>.
 * <p>
 * Using this annotation does nothing by itself; an annotation that makes lombok generate getters and setters,
 * such as {@link lombok.Setter} or {@link lombok.Data} is also required.
 */
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.SOURCE)
public @interface Accessors {
	/**
	 * If true, accessors will be named after the field and not include a {@code get} or {@code set}
	 * prefix. If true and {@code chain} is omitted, {@code chain} defaults to {@code true}.
	 * <strong>default: false</strong>
	 * 
	 * @return Whether or not to make fluent methods (named {@code fieldName()}, not for example {@code setFieldName}).
	 */
	boolean fluent() default false;
	/**
	 * If true, setters return {@code this} instead of {@code void}.
	 * <strong>default: false</strong>, unless {@code fluent=true}, then <strong>default: true</strong>
	 * 
	 * @return Whether or not setters should return themselves (chaining) or {@code void} (no chaining).
	 */
	boolean chain() default false;
	/**
	 * If present, only fields with any of the stated prefixes are given the getter/setter treatment.
	 * Note that a prefix only counts if the next character is NOT a lowercase character or the last
	 * letter of the prefix is not a letter (for instance an underscore). If multiple fields
	 * all turn into the same name when the prefix is stripped, an error will be generated.
	 * 
	 * @return If you are in the habit of prefixing your fields (for example, you name them {@code fFieldName}, specify such prefixes here).
	 */
	String[] prefix() default {};
}

另外如果一個(gè)類有些參數(shù)必傳,有些參數(shù)選傳,可以將必傳參數(shù)定義到構(gòu)造方法上,非必傳參數(shù)采用 @Accessor 方式鏈?zhǔn)皆O(shè)置。

// 導(dǎo)入 lombok 注解
import lombok.Data;
import lombok.experimental.Accessors;
// 定義 Person 類
@Getter // 自動(dòng)生成 getter 方法
@Accessors(chain = true) // 開啟鏈?zhǔn)秸{(diào)用
public class Person {
    // 定義必傳的屬性
    private String name; // 姓名
    private int id; // 編號(hào)
    // 定義選填的屬性
    private int age; // 年齡
    private String address; // 地址
    // 定義構(gòu)造函數(shù),接收必傳的參數(shù)
    public Person(String name, int id) {
        this.name = name;
        this.id = id;
    }
}
// 使用示例
public class Main {
    public static void main(String[] args) {
        // 創(chuàng)建一個(gè) Person 對(duì)象,傳入必要的參數(shù),通過鏈?zhǔn)秸{(diào)用,設(shè)置選填的屬性
        Person person = new Person("張三", 1001).setAge(25).setAddress("北京市");
        // 打印 Person 對(duì)象的信息
        System.out.println(person);
    }
}

4.2 手動(dòng)模擬 @Accessor

由于 @Accessor 在 lombok.experimental包下,有極個(gè)非常謹(jǐn)慎的人會(huì)擔(dān)心未來不穩(wěn)定,未來可能被移除。 其實(shí),在我看來這個(gè)擔(dān)心有些多余,目前這個(gè)注解比 @Builder 更適合使用,而且一個(gè)成熟的工具類庫(kù)不會(huì)輕易移除一個(gè)功能,而且及時(shí)移除了這個(gè)功能編譯期就可以感知到,替換起來也很容易。 如果真的擔(dān)心不穩(wěn)定或者不想依賴 lombok,那么自己在默認(rèn)生成的 Setter 方法上改造一下即可。

五、啟發(fā)

大多數(shù)同學(xué)使用 lombok 注解都不會(huì)主動(dòng)看源碼,了解有哪些高級(jí)配置。建議工作之余稍微花點(diǎn)時(shí)間去看一下源碼。 大家在使用 lombok 注解時(shí),一定要在腦海中能夠準(zhǔn)確“編譯” 出背后的代碼。如果你沒有這個(gè)能力,早晚會(huì)遇到坑。如果你沒有這個(gè)能力,那么多去看編譯后的類,熟能生巧。

并不是大家都在用的都是對(duì)的,使用某些功能時(shí)需要主動(dòng)思考是否正確,哪怕是正確的是否是最佳的。@Builder 注解的確和構(gòu)建器設(shè)計(jì)模式有些背離,很多時(shí)候我們需要的是@Accessor 的行為。

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

相關(guān)文章

  • MyBatis動(dòng)態(tài)創(chuàng)建表的實(shí)例代碼

    MyBatis動(dòng)態(tài)創(chuàng)建表的實(shí)例代碼

    在項(xiàng)目需求中,我們經(jīng)常會(huì)遇到動(dòng)態(tài)操作數(shù)據(jù)表的需求,常見的我們會(huì)把日志、設(shè)備實(shí)時(shí)位置信息等存入數(shù)據(jù)表,并且以一定時(shí)間段生成一個(gè)表來存儲(chǔ)。接下來通過本文給大家介紹MyBatis動(dòng)態(tài)創(chuàng)建表的方法,感興趣的朋友一起看看吧
    2018-07-07
  • 注解@TableName,@TableField,pgsql的模式對(duì)應(yīng)方式

    注解@TableName,@TableField,pgsql的模式對(duì)應(yīng)方式

    這篇文章主要介紹了注解@TableName,@TableField,pgsql的模式對(duì)應(yīng)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • 解決Maven項(xiàng)目pom.xml文件Ignored的問題

    解決Maven項(xiàng)目pom.xml文件Ignored的問題

    在Maven項(xiàng)目中,若不慎刪除了.iml文件,可能會(huì)導(dǎo)致pom.xml文件顯示為Ignored狀態(tài),影響項(xiàng)目構(gòu)建,解決方法是通過IDEA的設(shè)置取消Ignored Files中對(duì)應(yīng)文件的忽略,再刷新Maven項(xiàng)目即可恢復(fù),此操作可有效解決pom.xml文件被誤忽略的問題,保證項(xiàng)目正常構(gòu)建和運(yùn)行
    2024-09-09
  • SpringBoot Maven項(xiàng)目依賴沖突問題排查與解決全攻略

    SpringBoot Maven項(xiàng)目依賴沖突問題排查與解決全攻略

    本文將深入剖析SpringBoot項(xiàng)目中關(guān)于Maven依賴沖突問題的排查與解決,文內(nèi)會(huì)提供三種實(shí)用排查方案與實(shí)戰(zhàn)代碼,希望可以幫助大家徹底搞定依賴沖突
    2026-03-03
  • java Socket簡(jiǎn)易聊天工具

    java Socket簡(jiǎn)易聊天工具

    這篇文章主要為大家詳細(xì)介紹了java Socket簡(jiǎn)易聊天工具,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • Mybatis-plus查詢語句加括號(hào)(.or(),.and())問題

    Mybatis-plus查詢語句加括號(hào)(.or(),.and())問題

    這篇文章主要介紹了Mybatis-plus查詢語句加括號(hào)(.or(),.and())問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • 關(guān)于Logback+MyBatis日志輸出問題的一些思考

    關(guān)于Logback+MyBatis日志輸出問題的一些思考

    這篇文章主要介紹了關(guān)于Logback+MyBatis日志輸出問題的一些思考,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,
    2023-09-09
  • SpringBoot整合Kafka實(shí)現(xiàn)高可用消息隊(duì)列集群詳解

    SpringBoot整合Kafka實(shí)現(xiàn)高可用消息隊(duì)列集群詳解

    Apache?Kafka是一個(gè)分布式流處理平臺(tái),這篇文章主要介紹了SpringBoot如何整合Kafka實(shí)現(xiàn)高可用消息隊(duì)列集群,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下
    2026-01-01
  • 手把手教你搭建第一個(gè)Spring Batch項(xiàng)目的步驟

    手把手教你搭建第一個(gè)Spring Batch項(xiàng)目的步驟

    這篇文章主要介紹了手把手教你搭建第一個(gè)Spring Batch項(xiàng)目的步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Java AOP實(shí)現(xiàn)自定義滑動(dòng)窗口限流器方法詳解

    Java AOP實(shí)現(xiàn)自定義滑動(dòng)窗口限流器方法詳解

    這篇文章主要介紹了Java AOP實(shí)現(xiàn)自定義滑動(dòng)窗口限流器方法,其中滑動(dòng)窗口算法彌補(bǔ)了計(jì)數(shù)器算法的不足,滑動(dòng)窗口算法把間隔時(shí)間劃分成更小的粒度,當(dāng)更小粒度的時(shí)間間隔過去后,把過去的間隔請(qǐng)求數(shù)減掉,再補(bǔ)充一個(gè)空的時(shí)間間隔,需要的朋友可以參考下
    2022-07-07

最新評(píng)論

阜宁县| 淳化县| 阿荣旗| 仲巴县| 镇宁| 治多县| 东城区| 临江市| 中阳县| 西青区| 天峻县| 湘潭市| 凉城县| 贵州省| 西平县| 河东区| 乐至县| 额尔古纳市| 临城县| 宁晋县| 德阳市| 富锦市| 随州市| 龙岩市| 志丹县| 五莲县| 罗平县| 乌拉特后旗| 邢台县| 上蔡县| 凤山市| 孝义市| 庐江县| 翁牛特旗| 平谷区| 普安县| 周口市| 文水县| 遂宁市| 澄城县| 南昌市|