使用Lombok的@Builder注解时,Javadoc出现“找不到符号”错误。

43

我有一个类,看起来像下面这样:

@Data
@Builder
public class Foo {
    private String param;

    /** My custom builder.*/
    public static FooBuilder builder(String _param){
        return builder().param(_param);
    }
}

我遇到了以下错误:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-javadoc-plugin:2.10.4:javadoc (default-cli) on project foo: 在生成JavaDocs报告时发生了错误:
[ERROR] 退出代码:1 - /home/workspace/foo/src/main/java/com/foo/Foo.java:34: 错误:找不到符号
[ERROR] public static FooBuilder builder(String _param)
[ERROR] ^
[ERROR] 符号: 类 FooBuilder
[ERROR] 位置: 类 Foo

5个回答

35

Lombok可以填写部分定义的构建器类,因此您可以声明足够的构建器使Javadoc满意,然后就可以了。无需进行delombok。

在这种情况下,以下方法适用于我:

@Data
@Builder
public class Foo {
    private String param;

    // Add this line and all is good
    public static class FooBuilder {}

}

顺便提一下:你实际上可以使用这个技术添加一些自定义的构建器方法,所以它有优点。当我有集合时,我喜欢重载构建器方法,这样我就可以逐个添加项。可能已经有一些技术可以做到这一点,但知道你可以手动改进构建器是很好的。

这是我喜欢做的常见事情:

@Builder
public class Foo {
    private final String command;
    private final List<String> params;
    private final boolean background;
    
    public static class FooBuilder {
        public FooBuilder params(final String... params) {
            this.params = Arrays.asList(params);
            return this;
        }
    }
}
在上面的代码中,params 构建器方法已被自定义为接受可变参数。其他构建器方法仍将由 Lombok 创建。

1
谢谢!它很好用(JDK 8,Lombok 1.8.12,Mapstruct 1.3.1),并且让我们免受Delombok的困扰 :-) - t0r0X
1
我刚遇到这个问题,并发现只需要空的FooBuilder声明。可以放弃更大的builder(..)函数。(JDK17,Lombok 1.18.22)。 - Chris K
@ChrisK 正确。我添加了额外的构建器方法作为侧注中提到的自定义示例。我会澄清,以便清楚最低要求是什么。 - David Blevins

25
为了解决这个问题,我必须使用Lombok的delombok功能(详见:https://projectlombok.org/features/delombok)。

Lombok并不能覆盖所有工具。例如,Lombok无法插入JavaDoc……它们在运行Java源代码时。通过使用Delombok,你仍然可以将Lombok与这些工具一起使用,通过对你的Java代码进行预处理,使得所有的Lombok转换都已经应用到了Java代码中。

我使用Maven完成了这个过程,只需添加以下插件:

<plugin>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok-maven-plugin</artifactId>
    <version>1.18.0.0</version>
    <configuration>
        <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
        <outputDirectory>${delombok.output}</outputDirectory>
        <addOutputDirectory>false</addOutputDirectory>
    </configuration>
    <executions>
        <execution>
            <phase>generate-sources</phase>
            <goals>
                <goal>delombok</goal>
            </goals>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-javadoc-plugin</artifactId>
    <version>2.9</version>
    <configuration>
        <sourcepath>${delombok.output}</sourcepath>
    </configuration>
</plugin>

1
有没有其他方法可以使用javadoc-plugin处理注释,例如@Builder?就像编译器插件有<annotationProcessorPaths>一样?使用delombok听起来像是一种反模式。 - Naman
是的,听起来是这样,但我认为没有其他方法,即使lombok文档也肯定了它(参见我的回答)。 - yunandtidus
5
默认的delombok.outputDirectory${project.build.directory}/generated-sources/delombok,因此您只需要在maven-javadoc-plugin中指定它即可。 - osundblad

3

更新

如果您使用maven-javadoc-plugin 3.2.0及以上版本,您可以像这样配置它:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-javadoc-plugin</artifactId>
    <version>3.2.0</version>
    <configuration>
      <doclint>none</doclint>
    </configuration>
  </plugin>
doclint 配置将使 javadoc 插件不再抛出错误。它还将禁用 lint,但如果您可以接受这一点,则可能是代替 delombok 的最佳方式。
如果您使用任何 CI 工具构建和编译项目,可以创建一个单独的作业来检查 javadoc lint。
对我而言,在构建中禁用 lint 并不是一件坏事。Javadoc 很重要,但不应因为我使用 Lombok 而阻止我构建我的应用程序。

在JDK 20中不起作用。 - Lenny Primak
如果使用类似 @RequiredArgsConstructor(onConstructor = @__(@Inject)) 的东西,它就无法工作。 - Bing Ren

1
这很可能不是你的情况。但我遇到过这种情况,是因为构建中出现了其他问题。常见的问题是使用mapstruct生成类时失败,导致构建停止,而lombok无法生成所需内容。
然后,在引用构建器时会出现构建错误,因为它从未被构建。然而,这不是lombok的问题,而是构建问题。
再次强调,这很可能不是你的情况。但我从未见过其他情况下出现这个问题。

0

另一种解决方案是不在导入中包含BuilderClass。而是只导入父类,并将构建器类型的声明更改为parentClass.builderClass

@Getter
@RequiredArgsConstructor
@Builder
public class Foo {
    private final String param;
}

import com.Foo;
//import com.Foo.FooBuilder;

public class Bar {

    public Foo newFoo(String paramValue) {
        Foo.FooBuilder builder = Foo.builder();
        return builder.param(paramValue)
                  .build();
    }

}

1
当在另一个类中遇到问题时,这将起作用。不过,仔细看原始问题,建造者正在定义它的类中使用。在这种情况下,这种方法行不通,您需要使用@DavidBlevins的解决方案。 - Mike Cordeiro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接