使用 JavaPoet 实现生成的接口

Implementing generated interface with JavaPoet

我想使用 JavaPoet 生成一个接口和一个 class 实现这个接口。

TypeSpec if = TypeSpec.interfaceBuilder("MyInterface")
                      .build();

TypeSpec cl = TypeSpec.classBuilder("MyClass")
                      .build();

但我很想告诉 JavaPoet MyClass 应该实现 MyInterface。方法 addSuperinterface(TypeName) 需要一个类型名称,我不知道如何将 TypeSpec 变成 TypeName。我找到的唯一方法是调用 ClassName#get(String, String)

有没有更好的方法来实现这一点并直接使用接口的类型规范?

它并不像看起来那么复杂。 TypeSpec.Builder 有两个版本的 addSuperInterface 方法:

TypeSpec.Builder    addSuperinterface(Type superinterface) 
TypeSpec.Builder    addSuperinterface(TypeName superinterface)

例如,我们可以使用第二个版本,并使用 ClassName.get

获取超级接口作为 TypeName class 的实例

ClassName class 的 get 方法的签名之一是:

public static ClassName get(String packageName, String simpleName, String... simpleNames)

因此我们可以将它与空字符串一起用于包名称,因为您没有在接口规范中指定任何包名称。它会起作用,因为 ClassName extends TypeName。 另一方面,我们可以使用类型规范的名称 属性.

获取接口的简单名称

这里是一个完整的示例实现。我修改了变量的名称(您用于接口规范的变量名称 if 将不起作用,因为它是 java 关键字)。

@Data
public class SimpleClassSpecs {

    public final TypeSpec interfaceSpec;
    public final TypeSpec classSpec;

    public SimpleClassSpecs() {
        interfaceSpec = TypeSpec.interfaceBuilder("MyInterface")
                .build();

        TypeName interfaceTypeName = ClassName.get("", interfaceSpec.name);
        classSpec = TypeSpec.classBuilder("MyClass")
                .addSuperinterface(interfaceTypeName)
                .build();
    }
}

我使用 Lombok 的 @Data 作为样板代码(getters 和 setters...) 下面是一个对应的测试(用assertj写的断言):

@Test
public void should_generate_spec_with_superInterface() {
   SimpleClassSpecs ps = new SimpleClassSpecs();
   assertThat(ps.classSpec.toString()).contains("class MyClass implements MyInterface");
}

或者简单地做一个System.out.println(ps.classSpec),可以得到如下结果:

class MyClass implements MyInterface {
}