在 Groovy 2.1.6 脚本中,我定义了一个字段:
import groovy.transform.Field
@Field String test = "abc";
println "Script: ${test}";
def run = new Runnable() {
void run() {
println "Runnable0: ${test}";
new Runnable() {
void run() {
println "Runnable1: ${test}";
}
}.run();
}
}.run();
当从脚本中的匿名类访问它时,如 here ,Groovy 似乎试图将此字段转换为引用,并在定义 Runnable 后立即抛出以下异常:
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'abc' with class 'java.lang.String' to class 'groovy.lang.Reference'
at bug1.run(bug1:5)
此外,如果我将匿名 Runnable 放入类似 here 的函数中, Groovy 没有强制转换的问题,但是在内部的 Runnable 中找不到 Field:
groovy.lang.MissingFieldException: No such field: test for class: bug2$1
at bug2$1.this$dist$get$1(bug2.groovy)
at bug2$1$2.propertyMissing(bug2.groovy)
at bug2$1$2.run(bug2.groovy:14)
at java_lang_Runnable$run.call(Unknown Source)
at bug2$1.run(bug2.groovy:12)
at java_lang_Runnable$run.call(Unknown Source)
at bug2.fun(bug2.groovy:9)
at bug2.run(bug2.groovy:5)
这可以通过重新定义像here 这样的字段来解决。 , 但此修复仅在函数内部有效
这是 Groovy 中的错误还是我只是违反了一些规则而 Groovy 只是缺少适当的异常?
最佳答案
如果调用匿名类并引用字段变量,则不需要 @Field
转换。
原因:
当脚本中的严格类型变量定义为 @Field
时,该变量(在编译时 [AST 转换])在该脚本中被视为私有(private)变量。因此缺少属性。
为了了解差异,只需从 Groovy 控制台在 AST 浏览器中可视化脚本并在两种情况下(不使用和使用 @Field)进行“语义分析”阶段,您会注意到该变量是 run()
的本地变量主脚本与分别在全局定义的相比。
推论:
另一方面,当在同一脚本中的方法中使用严格类型的变量时,@Field
转换很有用,因为如果没有 @Field
,该字段将在脚本的 run()
方法中声明为局部变量,因此对其他方法不可见.
详情摘自 AST browser。
关于java - 匿名类中的 Groovy 脚本字段访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18725769/