Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Groovy'的意外行为;与';方法-变量分配静默失败_Groovy_Closures - Fatal编程技术网

Groovy'的意外行为;与';方法-变量分配静默失败

Groovy'的意外行为;与';方法-变量分配静默失败,groovy,closures,Groovy,Closures,我有以下代码: import groovy.transform.ToString @ToString(includeNames = true) class Simple { String creditPoints } Simple simple = new Simple() simple.with { creditPoints : "288" } println simple 显然,我在这里犯了一个错误,积分:“288”。它应该是creditPoints=“288” 我预计Groo

我有以下代码:

import groovy.transform.ToString
@ToString(includeNames = true)
class Simple {
  String creditPoints
}
Simple simple = new Simple()
simple.with {
    creditPoints : "288"
}
println simple
显然,我在这里犯了一个错误,
积分:“288”
。它应该是
creditPoints=“288”

我预计Groovy在运行时会失败,说我犯了一个错误,我应该使用
creditPoints=“288”
,但显然没有


既然它没有失败,那么Groovy对我创建的闭包做了什么?

从Groovy编译器的角度来看,闭包代码中没有错误。编译器将
creditPoints:“288”
视为Groovy编程语言中的合法构造。正如文档所述,label语句不会向生成的字节码添加任何内容,但它可以被AST转换使用(Spock框架大量使用)

如果您能根据标签语句用例更准确地设置代码的格式,它就会变得更清晰、更容易理解,例如

class Simple {
    String creditPoints

    static void main(String[] args) {

        Simple simple = new Simple()
        simple.with {
            creditPoints:
            "288"
        }
        println simple
    }
}
(注意:我将脚本放在
main
方法体中,以便在下一节中向您展示它的字节码表示形式。)

现在,当我们知道编译器如何看待这个构造时,让我们来看看最后字节码看起来是什么样子。为此,我们将反编译
.class
文件(我使用IntelliJ IDEA-您只需在IDEA中打开
.class
文件,它将为您反编译):

//
//IntelliJ IDEA从.class文件重新创建的源代码
//(由Fernflower反编译器提供动力)
//
导入groovy.lang.Closure;
导入groovy.lang.GroovyObject;
导入groovy.lang.MetaClass;
导入groovy.transform.ToString;
导入org.codehaus.groovy.runtime.DefaultGroovyMethods;
导入org.codehaus.groovy.runtime.GeneratedClosure;
导入org.codehaus.groovy.runtime.InvokerHelper;
@托斯特林
公共类简单实现GroovyObject{
私有字符串积分;
公共简单(){
元类var1=this.$getStaticMetaClass();
this.metaClass=var1;
}
公共静态void main(字符串…参数){
简单=新的简单();
类_main_closure1扩展闭包实现生成闭包{
public _main _closure1(对象_outerInstance,对象_thisObject){
super(_outrinsity,_thisObject);
}
公共对象doCall(对象it){
返回“288”;
}
公共对象调用(对象参数){
返回此.doCall(args);
}
公共对象调用(){
返回此.doCall((Object)null);
}
公共对象doCall(){
返回此.doCall((Object)null);
}
}
DefaultGroovyMethods.with(simple,new_main_closure1(simple.class,simple.class));
DefaultGroovyMethods.println(Simple.class,Simple);
对象var10000=null;
}
公共字符串toString(){
StringBuilder_结果=新建StringBuilder();
Boolean$toStringFirst=Boolean.TRUE;
_result.append(“简单(”);
如果($toStringFirst==null?错误:$toStringFirst){
Boolean var3=Boolean.FALSE;
}否则{
_结果。追加(“,”);
}
if(this.getCreditPoints()==this){
_result.append(“(this)”);
}否则{
_append(InvokerHelper.toString(this.getCreditPoints());
}
_结果。追加(“)”;
返回_result.toString();
}
公共字符串getCreditPoints(){
返回此.creditPoints;
}
公共无效设定点(字符串var1){
this.creditPoints=var1;
}
}
如您所见,与
with
方法一起使用的闭包表示为一个内部
\u main\u closure1
类。该类扩展了
Closure
类,并实现了
GeneratedClosure
接口。闭包的主体封装在
公共对象doCall(objectit)
方法中。此方法仅返回
“288”
字符串,这是预期的-默认情况下,闭包的最后一条语句将成为返回语句。生成的字节码中没有label语句,这也是由于标签在
规范化
Groovy编译器阶段被剥离的结果。

我通过您的代码“Simple(creditPoints:null)”实现了这一点