首页 > 解决方案 > 可以直接引用使用@Builder 声明的构建器类吗?

问题描述

以下 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)

标签: groovycompiler-errors

解决方案


那是对的。线

Foo.FooBuilder aBuilder = Foo.builder()

Phases.SEMANTIC_ANALYSIS将在尝试解析所有预期类型(左侧声明的类型)的阶段失败。Phases.CLASS_GENERATION这个阶段在生成类之前执行FooBuilder- 这就是编译器抱怨不存在的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关键字并依赖类型推断效果最好。


推荐阅读