You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Groovy AST转换中继承泛型基类Resource<A>?

问题:生成泛型父类的ClassNode时遇到编译器错误

我有一个Java抽象基类Resource<A>,包含A类型的attributes属性。现在要编写一个针对FooAttributes的AST转换,生成继承Resource<FooAttributes>的包装类FooResource,但处理ClassNode时遇到错误。

尝试的代码

make(rc.fqcn).tap {
  superClass = makeWithoutCaching(Resource).tap { genericsTypes = [attr] as GenericsType[] }
}

编译器错误信息

transform used a generics containing ClassNode com.example.Resource<com.example.FooAttributes> for the super class com.example.FooResource directly. You are not supposed to do this. Please create a new ClassNode referring to the old ClassNode and use the new ClassNode instead of the old one. Otherwise the compiler will create wrong descriptors and a potential NullPointerException in TypeResolver in the OpenJDK. If this is not your own doing, please report this bug to the writer of the transform.

(注:推测错误信息中“super class”应为“super class for”)

我查阅了ClassNode和ClassHelper的API,但未找到“创建引用旧节点的新节点”的方法。尝试调用new ClassNode(String, int, ClassNode)仍出现相同错误。请问应使用哪些API调用来为泛型类Resource<A>创建新的ClassNode?


解决方案

核心思路是创建独立的、带泛型参数的ClassNode引用,而非直接修改原Resource的ClassNode,避免污染复用的节点。可以通过以下两种方式实现:

方式一:通过TypeReference生成泛型类型再创建ClassNode

// 生成带泛型参数的Resource类型引用
def resourceType = new TypeReference(Resource) {}.getType()
def genericResourceType = new GenericType(resourceType, attr)

// 基于泛型类型创建父类ClassNode
make(rc.fqcn).tap {
  superClass = ClassHelper.makeClassNode(genericResourceType)
}

方式二:直接使用ClassHelper的makeWithGenerics工具方法

// 直接创建带指定泛型参数的Resource ClassNode
def superClassNode = ClassHelper.makeWithGenerics(Resource, [attr] as GenericsType[])

// 为生成的FooResource设置父类
make(rc.fqcn).tap {
  superClass = superClassNode
}

这两种方法都会生成一个全新的ClassNode,它仅引用原Resource类的元信息,不会修改原节点,符合编译器对AST转换的要求,能解决错误提示中的问题。


内容的提问来源于stack exchange,提问作者chrylis -cautiouslyoptimistic-

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 13:20:30