【问题标题】:Is it possible to make Lombok's builder public?是否可以将龙目岛的建造者公之于众?
【发布时间】:2018-01-18 09:42:37
【问题描述】:

我在我的项目中使用 Lombok 库,我无法在外部包中使用带有 @Builder 注释的类。

有没有办法让构建器公开?

MyClass instance = new MyClass.MyClassBuilder().build();

错误是:

'MyClassBuilder()' 在 'com.foo.MyClass.MyClassBuilder'。无法访问 外包装

【问题讨论】:

    标签: java lombok


    【解决方案1】:

    @Builder 已经产生了公共方法,它只是包私有的构造函数。原因是他们打算让你使用静态的builder() 方法,它是公共的,而不是直接使用构造函数:

    Foo foo = Foo.builder()
        .property("hello, world")
        .build();
    

    如果你真的,真的,真的希望构造函数是公共的(似乎有一些建议表明其他基于反射的库可能需要它),那么 Lombok 将永远不会覆盖你的任何东西'已经显式声明了,因此您可以使用公共构造函数声明这样的骨架,Lombok 将填充其余部分,而无需将构造函数更改为包私有或任何东西。

    @Builder
    public class Foo
    {
        private final String property;
    
        public static class FooBuilder
        {
            public FooBuilder() { }
    
            // Lombok will fill in the fields and methods
        }
    }
    

    这种允许部分实现覆盖默认行为的一般策略也适用于大多数(可能是所有)其他 Lombok 注释。如果您的类使用@ToString 进行注释,但您已经声明了toString 方法,它将不理会您的方法。

    为了向您展示生成的所有内容,我编写了以下类:

    @Builder
    public class Foo
    {
        private final String property;
    }
    

    然后我通过delombok 运行它以查看生成的所有内容。如您所见,一切都是公开的:

    public class Foo
    {
        private final String property;
    
        @java.beans.ConstructorProperties({"property"})
        Foo(final String property) {
            this.property = property;
        }
    
        public static FooBuilder builder() {
            return new FooBuilder();
        }
    
        public static class FooBuilder
        {
            private String property;
    
            FooBuilder() { }
    
            public FooBuilder property(final String property) {
                this.property = property;
                return this;
            }
    
            public Foo build() {
                return new Foo(property);
            }
    
            public String toString() {
                return "Foo.FooBuilder(property=" + this.property + ")";
            }
        }
    }
    

    【讨论】:

    • 我试图直接使用新的构建器。谢谢你的回答。
    【解决方案2】:

    问题是你以错误的方式使用@Builder。

    使用Builder Pattern时,只需要使用静态方法调用即可构建,例如:

    MyClass instance = MyClass.builder().build();

    请不要再次newMyClassBuilder,因为您直接使用内部MyClassBuilder 类,它破坏了模式的封装。这个构造函数被隐藏在外面,这就是为什么你会得到不可访问的错误。相反,它为您提供了静态方法builder()

    【讨论】:

    • 那不是问题。如果我们需要在 masptruct 中显式使用 Builder 类,这是一个巨大的痛苦。生成的构造函数是包私有的
    • 到目前为止,我正在使用 @ObjectFactory public UserResponse.UserResponseBuilder resolveBuilder() { return UserResponse.builder(); } 解决 mapstruct 的这个问题
    【解决方案3】:

    我发现了这个巧妙的解决方法:

    import lombok.Builder;
    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    @Builder
    public class Customer {
        private String id;
        private String name;
    
        public static MessageBuilder builder() {return new CustomerBuilder();}
    }
    

    【讨论】:

      【解决方案4】:

      这个构建器注解的问题是,如果你delombok你会看到,生成器的构造器没有访问指示符(公共的、私有的、受保护的),因此只能在同一个包中看到。 如果扩展类在同一个包中,这将起作用。

      我遇到了同样的问题,我认为 lombok 目前不支持这个。 我可以在这里找到功能请求https://github.com/rzwitserloot/lombok/issues/1489

      我的建议是在这个类中硬实现构建器模式。

      【讨论】:

        【解决方案5】:

        如前所述,您可以使用构建器,现在 builder() 将返回实例创建而不是用户属性,因此您可以将其视为普通构建器(无需使用属性)

        instance = MyClass.MyClassBuilder().property1(value1).property1(value2).build();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-10
          • 2015-10-18
          • 1970-01-01
          • 1970-01-01
          • 2021-10-02
          • 2021-03-27
          相关资源
          最近更新 更多