您现在的位置是:亿华云 > IT科技

使用Lombok的@Builder注解实现构造器模式

亿华云2025-10-08 21:04:56【IT科技】9人已围观

简介译者 | 翟珂审校 | 梁策 孙淑娟概述我们将研究如何通过Lombok的@Builder注解让含有多个入参的方法更容易被调用,从而提高可用性。使用@Builder的简单方法怎样才能更灵活方便地调用多入

译者 | 翟珂

审校 | 梁策 孙淑娟

概述

我们将研究如何通过Lombok的使用实现式@Builder注解让含有多个入参的方法更容易被调用,从而提高可用性。注解

使用@Builder的构造简单方法

怎样才能更灵活方便地调用多入参方法呢?请看下面的例子:

void method(@NotNull String firstParam, @NotNull String secondParam,

String thirdParam, String fourthParam,

Long fifthParam, @NotNull Object sixthParam) {

...

}

如果非空参数是可选的,那么有以下几种调用方式:

method("A",器模 "B", null, null, null, new Object());

method("A", "B", "C", null, 2L, "D");

method("A", "B", null, null, 3L, this);

...

这个例子暴露了一些问题,比如:

调用者必须知道修改哪个参数(例如,使用实现式第一个调用方法如果改为第二个,注解调用者必须知道要修改第五个为Long类型参数)。构造入参顺序不可改变。器模需要传入的使用实现式参数名称不可见。

从提供者的注解角度来看,如果要提供参数较少的构造方法则需要大量重载,如下:

void method(@NotNull String firstParam,器模 @NotNull String secondParam, @NotNull Object sixthParam);

void method(@NotNull String firstParam, @NotNull String secondParam, String thirdParam, @NotNull Object sixthParam);

void method(@NotNull String firstParam, @NotNull String secondParam, String thirdParam, String fourthParam, @NotNull Object sixthParam);

void method(@NotNull String firstParam, @NotNull String secondParam, String thirdParam, String fourthParam, Long fifthParam, @NotNull Object sixthParam);

...

为了提高可用性且避免重复代码,我们可以使用方法构建器。使用实现式Lombok项目已经提供了一个注解,注解它可以使生成构建器变得更简单。构造因此,上面的例子可以改造为以下方式:

@Builder(builderMethodName = "methodBuilder", buildMethodName = "call")

void method(@NotNull String firstParam, @NotNull String secondParam,

String thirdParam, String fourthParam,

Long fifthParam, @NotNull Object sixthParam) {

...

}

然后就可以这样调用方法:

methodBuilder()

.firstParam("A")

.secondParam("B")

.sixthParam(new Object())

.call();

methodBuilder()

.firstParam("A")

.secondParam("B")

.thirdParam("C")

.fifthParam(2L)

.sixthParam("D")

.call();

methodBuilder()

.firstParam("A")

.secondParam("B")

.fifthParam(3L)

.sixthParam(this)

        .call();

这样一来,方法的可读性及灵活性都提高了。

默认情况下,一个静态方法的builder方法(获得构建器实例的方法)就是一个静态方法。服务器租用默认情况下,call()方法将抛出原方法的异常。

默认值

在许多情况下,需要去为方法的入参指定默认值,而Java与其他一些语言不同,它没有语义来支持这一需求。因此,在大多数情况下,它都是通过方法重载来实现的,如下:

method() { method("Hello"); }

method(String a) { method(a, "builder"); }

method(String a, String b) { method(a, b, "world!"); }

method(String a, String b, String c) { ... acutal logic here ... }

当使用Lombok builder时,会在目标类中生成一个构建器类。这个构建器类:

拥有与方法相同数量的属性和参数。有参数的set方法。

该类也可以手动定义,这样就可以为参数定义默认值。上面的方法也就可以写成:

@Builder(builderMethodName = "methodBuilder", buildMethodName = "call", builderClassName = "MethodBuilder")

method(String a, String b, String c) {

... acutal logic here ...

}

private class MethodBuilder {

private String a = "Hello";

private String b = "builder";

private String c = "world!";

}

有了这个补充,如果调用者没有指定一个参数,那么将使用构建器类中定义的默认值。

注意:在这种情况下,我们不需要在类中声明该方法的所有入参,Lombok会自动配置。

泛型方法

我们会有通过入参去定义返回类型的需求,例如:

public <T> T read(byte[] content, Class<T> type) { ...}

在这种情况下,香港云服务器builder类将是一个泛型类,但是builder方法将创建一个没有约束类型的实例。请看下面的例子:

@Builder(builderMethodName = "methodBuilder", buildMethodName = "call", builderClassName = "MethodBuilder")

public <T> T read(byte[] content, Class<T> type) { ...}

在这种情况下,methodBuilder方法将创建一个没有约束类型的MethodBuilder实例。这导致下面的代码不会被编译(入参定义为Class,传入Class):

methodBuilder()

.content(new byte[]{ })

.type(String.class)

    .call();

上述问题可以通过强制转换类型来解决:

methodBuilder()

.content(new byte[]{ })

.type((Class)String.class)

    .call();

这样,它就可以通过编译。但是这么使用,调用方法后返回的类型不是String,而是未知类型的泛型T。

String result = (String)methodBuilder()

.content(new byte[]{ })

.type((Class)String.class)

    .call();

那么,我们需要再将输出结果进行强制转换。而我们最初的目的是提供一种方便调用者的方法,因此建议考虑下面的两种解决方案之一。

覆盖Builder方法

如上所述,问题的根源在于builder方法在没有传入特定类型参数的源码库情况下,创建了builder类的实例。所以我们可以在类中重载构建器方法,并实例化一个指定类型的构建器类:

@Builder(builderMethodName = "methodBuilder", buildMethodName = "call", builderClassName = "MethodBuilder")

public T read(final byte[] content, final Classtype) { ...}

public MethodBuildermethodBuilder(final Classtype) {

return new MethodBuilder().type(type);

}

public class MethodBuilder{

private Classtype;

public MethodBuildertype(Classtype) { this.type = type; return this; }

public T call() { return read(content, type); }

}

在这种情况下,调用者不需要进行强制类型转换,调用过程如下:

List result = methodBuilder(List.class)

.content(new byte[]{ })

    .call(); 在setter方法中强制转换

也可以在类型参数set方法中强转构建器实例类型:

@Builder(builderMethodName = "methodBuilder", buildMethodName = "call", builderClassName = "MethodBuilder")

public T read(final byte[] content, final Classtype) { ...}

public class MethodBuilder{

private Classtype;

public MethodBuildertype(final Classtype) {

this.type = (Class)type;

return (MethodBuilder) this;

}

public T call() { return read(content, type); }

}

使用这种方式就不需要手动定义构建器方法。从调用者的角度来看,类型参数就像其他参数一样直接传入。

结论

在方法上使用@Builder可以带来以下优势:

提高了调用者的灵活性在不写重载方法的前提下,可以定义参数的默认值提高了方法调用的可读性可以通过同一个builder实例进行类似的调用

需要注意的是,在某些情况下,使用方法构建器会给提供者带来不必要的复杂情况。各类方法构建器的demo可参考GitHub上的信息。

译者介绍

翟珂,社区编辑,目前在杭州从事软件研发工作,做过电商、征信等方面的系统,享受分享知识的过程,充实自己的生活。

原文标题:​​Method Builder With Lombok @Builder​​,作者:Daniel Buza

很赞哦!(7)