可以直接引用用@Builder声明的生成器类吗?

时间:2018-09-20 17:18:35

标签: groovy compiler-errors

以下Groovy脚本无法编译:

import groovy.transform.builder.Builder

@Builder
class Foo {
    String bar
}

Foo.FooBuilder aBuilder = Foo.builder()

编译错误为:

  

错误:(8,16)Groovyc:无法解析类Foo.FooBuilder

这是预期的行为吗?有任何已知的解决方法吗?

Groovy版本:2.5.2(我也检查了2.4.12和2.4.15)

1 个答案:

答案 0 :(得分:1)

是正确的。线

Foo.FooBuilder aBuilder = Foo.builder()

将在Phases.SEMANTIC_ANALYSIS阶段失败,该阶段尝试解析所有预期的类型(在左侧声明的类型)。此阶段在生成FooBuilder类的Phases.CLASS_GENERATION之前执行-这就是为什么编译器会抱怨不存在的FooBuilder类(它根本还没有生成)。

解决方法

有一个解决此问题的简单方法-使用def并键入推断以通过语义分析阶段,并使编译器生成FooBuilder类。

import groovy.transform.builder.Builder

@Builder
class Foo {
    String bar
}

def aBuilder = Foo.builder()

println aBuilder.dump()

请注意-有一种方法可以使Foo.FooBuilder aBuilder = Foo.builder() 通过静态分析阶段。如果您跳过声明Foo.FooBuilder的类型

import groovy.transform.builder.Builder

@Builder
class Foo {
    String bar
}

//Foo.FooBuilder aBuilder = Foo.builder()

并使用groovyc编译器编译此类,它将生成Foo.classFoo$FooBuilder.class。然后,如果您取消注释引发编译异常的行并运行了脚本,则它将编译并运行而没有任何问题。诀窍是Groovy编译器会编译Foo.FooBuilder类(并将其保存为Foo$FooBuilder.class文件),因此,当您运行脚本并进行静态分析尝试解析它时,它可在当前类路径中使用。在这种情况下,语义分析阶段不会报告您先前遇到的错误。但是,我仅将其作为一个有趣的事实而不是变通办法来提及,因为它很难使用。在这种情况下,最好使用def关键字并依靠类型推断。