groovy@Builder AST中的默认值

groovy@Builder AST中的默认值,groovy,Groovy,我是groovy新手,我只是想在这里学习。我有一个简单的pojo,如下所示,我试图在这里有一个构建器模式。现在,该类使用@Builder注释进行注释 @Builder class Invert { String color = 'Green' String code } 在我的主类中,如果创建反转类的对象,则变量color始终为null Invert in = new Invert.builder().code('0000').build() 对象创建时代码为0000

我是groovy新手,我只是想在这里学习。我有一个简单的pojo,如下所示,我试图在这里有一个构建器模式。现在,该类使用@Builder注释进行注释

@Builder
class Invert {
      String color = 'Green'
      String code
}
在我的主类中,如果创建反转类的对象,则变量color始终为null

Invert in = new Invert.builder().code('0000').build()

对象创建时代码为0000,但颜色为null。是预期的吗?如果是的话,是否有任何解决方法,或者我在这里遗漏了什么?

首先,让我告诉您发生了什么。我将从
Invert
类开始:

@groovy.transform.builder.Builder
class Invert {
      String color = 'Green'
      String code
}
这与您的示例中的类相同,唯一的区别是
@Builder
的完全限定名。但请查看Groovy编译代码时会发生什么(这是Groovy控制台中AST查看器中的相关代码)

反向类 这并不奇怪,不过请注意,构造函数中的
颜色设置为
绿色

反转$InvertBuilder类
Invert$InvertBuilder
类由
@Builder
AST创建。它提供了fluent API

问题 你找到问题的根源了吗?生成器包含自己的
颜色
代码
字段。然后,当调用
build()
时:

  • 将创建
    Invert
    的实例。此时,实例的
    颜色
    绿色
  • 构建器将自己的
    颜色
    代码
    字段应用于
    反转
    实例。此时,
    颜色
    更改为null,因为这是生成器中的默认值
  • 解决方案 要使用生成器解决此问题,请使用
    ExternalStrategy
    定义自己的生成器类,在该类中可以根据需要设置
    颜色。下面是一个工作示例:

    class Invert {
          String color
          String code
    
          static InvertBuilder builder() {
              new InvertBuilder()
          }
    }
    
    @groovy.transform.builder.Builder(builderStrategy=groovy.transform.builder.ExternalStrategy, forClass=Invert)
    class InvertBuilder {
        InvertBuilder() {
            color = 'Green'
        }
    }
    
    Invert invert = Invert.builder().code('0000').build()
    
    assert invert.color == 'Green'
    assert invert.code == '0000'
    
    选择 Groovy提供了一些您可能感兴趣的替代构建方法

    Invert invert1 = new Invert(code: '0000', color: 'Blue') // Using the Map-based constructor
    
    Invert invert2 = new Invert().with { // using Object.with(Closure)
        code = '0000'
        color = 'Blue'
    
        return delegate
    }
    

    首先,让我告诉你发生了什么。我将从
    Invert
    类开始:

    @groovy.transform.builder.Builder
    class Invert {
          String color = 'Green'
          String code
    }
    
    这与您的示例中的类相同,唯一的区别是
    @Builder
    的完全限定名。但请查看Groovy编译代码时会发生什么(这是Groovy控制台中AST查看器中的相关代码)

    反向类 这并不奇怪,不过请注意,构造函数中的
    颜色设置为
    绿色

    反转$InvertBuilder类
    Invert$InvertBuilder
    类由
    @Builder
    AST创建。它提供了fluent API

    问题 你找到问题的根源了吗?生成器包含自己的
    颜色
    代码
    字段。然后,当调用
    build()
    时:

  • 将创建
    Invert
    的实例。此时,实例的
    颜色
    绿色
  • 构建器将自己的
    颜色
    代码
    字段应用于
    反转
    实例。此时,
    颜色
    更改为null,因为这是生成器中的默认值
  • 解决方案 要使用生成器解决此问题,请使用
    ExternalStrategy
    定义自己的生成器类,在该类中可以根据需要设置
    颜色。下面是一个工作示例:

    class Invert {
          String color
          String code
    
          static InvertBuilder builder() {
              new InvertBuilder()
          }
    }
    
    @groovy.transform.builder.Builder(builderStrategy=groovy.transform.builder.ExternalStrategy, forClass=Invert)
    class InvertBuilder {
        InvertBuilder() {
            color = 'Green'
        }
    }
    
    Invert invert = Invert.builder().code('0000').build()
    
    assert invert.color == 'Green'
    assert invert.code == '0000'
    
    选择 Groovy提供了一些您可能感兴趣的替代构建方法

    Invert invert1 = new Invert(code: '0000', color: 'Blue') // Using the Map-based constructor
    
    Invert invert2 = new Invert().with { // using Object.with(Closure)
        code = '0000'
        color = 'Blue'
    
        return delegate
    }
    

    生成器API希望您使用生成器语法初始化每个属性。 通过不指定“color”属性的值,实际上是在默默地指定该值应为null,从而覆盖“Green”默认值

    您可以将代码调整为以下内容,这是我运行测试的一个简单groovy脚本:

    import groovy.transform.builder.*
    import groovy.transform.*
    
    @Canonical
    @Builder
    class Invert {
        String color
        String code
    }
    
    def invert = new Invert().builder().code('000').color('Green').build()
    println invert
    
    并不是说我使用生成器语法显式设置了颜色属性,结果如下:

    内底(绿色,000)

    还要注意使用的@Canonical注释。这是一个很好的注释,它结合了几个注释:

    @EqualsAndHashCode、@ToString和@TupleConstructor

    除了提供一个很好的toString()输出(可以在运行脚本的输出中看到),TupleConstructor(在我看来)比使用@Builder类型模式更可取

    使用@TupleConstructor,您可以像这样简单地构造反转对象:

    def invert = new Invert(code:'000', color:'Green')
    
    此外,TupleConstructor允许您保留为颜色设置的默认值,如果未在构造函数中设置,则不会覆盖该值:

    import groovy.transform.*
    
    @Canonical
    class Invert {
        String color = 'Green'
        String code
    }
    
    def invert = new Invert(code:'000')
    println invert
    
    结果如下:

    内底(绿色,000)

    因此,如果是我,我会删除@Builder并使用@Canonical作为最佳实践。 有关@Canonical的更多信息,请参阅:


    生成器API希望您使用生成器语法初始化每个属性。 通过不指定“color”属性的值,实际上是在默默地指定该值应为null,从而覆盖“Green”默认值

    您可以将代码调整为以下内容,这是我运行测试的一个简单groovy脚本:

    import groovy.transform.builder.*
    import groovy.transform.*
    
    @Canonical
    @Builder
    class Invert {
        String color
        String code
    }
    
    def invert = new Invert().builder().code('000').color('Green').build()
    println invert
    
    并不是说我使用生成器语法显式设置了颜色属性,结果如下:

    内底(绿色,000)

    还要注意使用的@Canonical注释。这是一个很好的注释,它结合了几个注释:

    @EqualsAndHashCode、@ToString和@TupleConstructor

    除了提供一个很好的toString()输出(可以在运行脚本的输出中看到),TupleConstructor(在我看来)比使用@Builder类型模式更可取

    使用@TupleConstructor,您可以像这样简单地构造反转对象:

    def invert = new Invert(code:'000', color:'Green')
    
    此外,TupleConstructor允许您保留为颜色设置的默认值,如果未在构造函数中设置,则不会覆盖该值:

    import groovy.transform.*
    
    @Canonical
    class Invert {
        String color = 'Green'
        String code
    }
    
    def invert = new Invert(code:'000')
    println invert
    
    结果如下:

    内底(绿色,000)

    所以,如果是我,我会移除@Builder和我们