groovy @Builder AST中的默认值 [英] Default Values in groovy @Builder AST
问题描述
我对groovy很陌生,我只是想在这里学习。我有一个简单的pojo如下,我想在这里有一个建设者模式。现在这个类用@Builder annotaion注释。
@Builder
类反转{
字符串颜色='绿色'
字符串代码
$ p在我的主类中,如果创建一个Invert类对象,则变量color始终为null 。
Invert in = new Invert.builder()。code('0000')。build()
使用代码创建对象为0000,但颜色为空。如果有的话,是否有任何解决方法,或者我在这里丢失了一些东西? 解决方案
首先,让我告诉你这是怎么回事。我将从 Invert
类开始:
@ groovy.transform .builder.Builder
class Invert {
String color ='Green'
String code
}
因此这与您的示例中的类相同,唯一的区别是 @Builder
的完全限定名称。但请看看Groovy编译代码时发生了什么(这是Groovy控制台中AST查看器的相关代码)。
$ b
Invert class
@ 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
。
反转$ InvertBuilder类
public static class Invert $ InvertBuilder implements groovy.lang.GroovyObject extends java.lang.Obje ct {
private java.lang.String color
private java.lang.String code
...
public Invert $ InvertBuilder color(java .lang.String color){
this .color = color
return this
}
public反转$ InvertBuilder代码(java.lang.String code){
this .code = code
return this
}
public反转build(){
反转_theInvert = new Invert()
_theInvert。 color = color
_theInvert .code = code
return _theInvert
}
...
}
b $ p
$Invert $ InvertBuilder
类是由@Builder code> AST。它提供了流畅的API。
问题
你有没有发现问题的根源?构建器包含它自己的
color
和code
字段。然后,当调用build()
时:
$ b
Invert
被创建。此时,实例的color 是
green
。
- 构建器应用它自己的
color 和
code
字段添加到Invert
实例中。此时,color
更改为null,因为这是构建器中的默认值。
解决方案
要使用构建器解决此问题,请使用
ExternalStrategy
来定义您自己的构建器类,您可以根据需要设置颜色
。这是一个可行的例子:
$ pre code $ class $ Invalid {
字符串颜色
字符串代码
static InvertBuilder builder(){
new InvertBuilder()
}
}
@ groovy.transform.builder.Builder(builderStrategy = groovy.transform.builder .ExternalStrategy,forClass = Invert)
class InvertBuilder {
InvertBuilder(){
color ='Green'
}
}
反转('0000')。build()
assert invert.color =='Green'
assert invert.code =='0000'
替代方案
Groovy提供了一些替代构建方法可能会感兴趣。
反转invert1 =新反转(代码:'0000',颜色:'蓝')//使用基于地图的构造函数
Invert invert2 = new Invert()。with {//使用Object.with(Closure)
code ='0000'
color ='Blue '
返回委托
}
I am new to groovy and i am just trying to learn here. I have a simple pojo as below, i am trying to have a builder pattern here. Now the class is annotated with @Builder annotaion.
@Builder
class Invert {
String color = 'Green'
String code
}
In my main class if create a object of Invert class, variable color is always null.
Invert in = new Invert.builder().code('0000').build()
Object is created with code as 0000 but color as null. Is it expected, if so is there any workaround for this or i am missing something here ?
First, let me show you what's going on. I'll start with the Invert
class:
@groovy.transform.builder.Builder
class Invert {
String color = 'Green'
String code
}
So that's the same class from your example, with the only difference being a fully-qualified name for @Builder
. But check out what happens when Groovy compiles the code (this is the relevant code from the AST viewer in the Groovy console).
Invert class
@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()
}
...
}
Nothing surprising, although note that the color
is set to green
in the constructor.
Invert$InvertBuilder class
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
}
...
}
The Invert$InvertBuilder
class is created by the @Builder
AST. It's what provides the fluent API.
The problem
Did you catch the source of the problem? The builder contains its own color
and code
fields. Then, when build()
is called:
- An instance of
Invert
is created. At this point, the instance'scolor
isgreen
. - The builder applies its own
color
andcode
fields to theInvert
instance. At this point thecolor
is changed to null because that's the default in the builder.
The solution
To solve this issue with a builder, use the ExternalStrategy
to define your own builder class, in which you can set the color
as you'd like. Here's a working example:
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'
Alternatives
Groovy provides some alternative building methods you may be interested in.
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
}
这篇关于groovy @Builder AST中的默认值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!