我是groovy的新手,我只是想在这里学习。我有一个简单的pojo如下,我想在这里有一个建设者模式。现在,该类使用@Builder annotaion进行注释。
@Builder
class Invert {
String color = 'Green'
String code
}
在我的主类中,如果创建一个Invert类的对象,变量颜色总是为空。
Invert in = new Invert.builder().code('0000').build()
创建对象时代码为0000但颜色为null。是否可以预料到,如果有这样的解决方法,或者我在这里遗漏了什么?
答案 0 :(得分:2)
首先,让我告诉你发生了什么。我将从Invert
类开始:
@groovy.transform.builder.Builder
class Invert {
String color = 'Green'
String code
}
这就是你的例子中的同一个类,唯一的区别是@Builder
的完全限定名。但是看看Groovy编译代码时会发生什么(这是Groovy控制台中AST查看器的相关代码)。
@groovy.transform.builder.Builder
public class Invert implements groovy.lang.GroovyObject extends java.lang.Object {
private java.lang.String color
private java.lang.String code
...
public Invert() {
color = 'Green'
metaClass = /*BytecodeExpression*/
}
public static Invert$InvertBuilder builder() {
return new Invert$InvertBuilder()
}
...
}
没什么好吃的,但请注意构造函数中color
设置为green
。
public static class Invert$InvertBuilder implements groovy.lang.GroovyObject extends java.lang.Object {
private java.lang.String color
private java.lang.String code
...
public Invert$InvertBuilder color(java.lang.String color) {
this .color = color
return this
}
public Invert$InvertBuilder code(java.lang.String code) {
this .code = code
return this
}
public Invert build() {
Invert _theInvert = new Invert()
_theInvert .color = color
_theInvert .code = code
return _theInvert
}
...
}
Invert$InvertBuilder
类由@Builder
AST创建。它提供了流畅的API。
您是否抓住了问题的根源?构建器包含自己的color
和code
字段。然后,当build()
被调用时:
Invert
的实例。此时,实例的color
为green
。color
和code
字段应用于Invert
实例。此时,color
更改为null,因为这是构建器中的默认值。要使用构建器解决此问题,请使用ExternalStrategy
定义您自己的构建器类,您可以在其中根据需要设置color
。这是一个有效的例子:
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
}
答案 1 :(得分:0)
Builder API要求您使用构建器语法初始化每个属性。 未指定“颜色”的值。属性,您实际上默默地指定该值应为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
不是我使用Builder语法显式设置颜色属性,结果为:
反转(绿色,000)
另请注意使用的@Canonical注释。这是一个很好的注释,结合了几个注释:
@EqualsAndHashCode,@ ToTtring和@TupleConstructor
除了提供一个很好的toString()输出,你可以在运行脚本的输出中看到,TupleConstructor(在我看来)比使用@Builder类型模式更可取。
使用@TupleConstructor,您可以像这样简单地构造您的Invert对象:
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的更多信息,请参阅:
http://docs.groovy-lang.org/next/html/gapi/groovy/transform/Canonical.html