使用命令行参数静态编译groovy脚本

使用命令行参数静态编译groovy脚本,groovy,compilation,command-line-arguments,Groovy,Compilation,Command Line Arguments,我试图静态编译groovy脚本以加快其执行速度,但如果使用命令行参数,则无法使其工作。我的实际脚本要长得多,但我用于这个问题的一行脚本完美地再现了我的错误 使用以下脚本(test.groovy) 这可以通过命令groovyctest.groovy编译,并通过java命令java-cp运行GROOVY_HOME%\lib\*测试,只需打印所用命令行参数的数量 现在,如果我提供脚本(config.groovy) 使用groovyc-configscript config.groovy test.gr

我试图静态编译groovy脚本以加快其执行速度,但如果使用命令行参数,则无法使其工作。我的实际脚本要长得多,但我用于这个问题的一行脚本完美地再现了我的错误

使用以下脚本(test.groovy)

这可以通过命令
groovyctest.groovy
编译,并通过java命令
java-cp运行GROOVY_HOME%\lib\*测试
,只需打印所用命令行参数的数量

现在,如果我提供脚本(config.groovy)

使用
groovyc-configscript config.groovy test.groovy
编译时,我得到一个错误

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
testing.groovy: 1: [Static type checking] - The variable [args] is undeclared.
 @ line 1, column 9.
   println(args.length)
           ^

1 error
此错误仅在尝试静态编译时发生。我可以通过将脚本包装在类中并将代码放入主方法(当然,这是编译器对脚本所做的),而不是在我尝试只使用脚本时(这是我更喜欢做的)。由于某些原因,静态编译时变量args是未知的。我尝试了
this.args
,但仍然收到错误。如果我尝试为args(
String[]args
)声明一个类型,它将不再接收命令行参数

当以这种方式静态编译脚本时,是否有方法仍然获取命令行参数


我在Windows7和Java8上使用Groovy 2.4.10版。

执行Groovy类和运行简单脚本是有区别的。编译器简单地将脚本包装在main方法中是不正确的,脚本的主体将被复制到
run
方法中

例如:

println(args.length)
将转换为

import org.codehaus.groovy.runtime.InvokerHelper
class Main extends Script {                     
    def run() {                                 
        println(args.length)              
    }
    static void main(String[] args) {           
        InvokerHelper.runScript(Main, args)     
    }
}
由于动态类型的原因,这可以很好地编译。 现在,如果我们向该类添加
@CompileStatic
注释,我们将得到未声明变量的错误

因此,为了使用静态编译,您必须将代码封装在类中


您可以在中阅读有关脚本与类的更多信息。

脚本通过动态评估绑定对象工作。如果要使用静态编译,则需要使用显式形式,将test.groovy脚本更改为以下内容:

String[] args = (String[])binding.getVariable('args')
println args.length
使用已经提供的配置脚本,您可以得到一个静态编译脚本。我以这种方式运行它:

groovyc --configscript config.groovy test.groovy
java -cp .;%GROOVY_HOME%\lib\groovy-2.5.3.jar test 1 2 3
这将打印
3

如果您不想修改test.groovy,可以创建一个新的基类:

import groovy.transform.CompileStatic

@CompileStatic
abstract class StaticBase extends Script {
    StaticBase() {
    }

    StaticBase(Binding binding) {
        super(binding)
    }

    String[] getArgs() {
        (String[]) getBinding().getVariable("args")
    }
}
由于基类有一个方法
getArgs
,因此当test.groovy引用args时,静态编译器将调用该方法

groovyc --configscript config.groovy -b StaticBase test.groovy
java -cp .;%GROOVY_HOME%\lib\groovy-2.5.3.jar test 1 2

test.class中的代码有一个run方法,其代码表示
this.println(this.getArgs().length)

我不知道我怎么会错过它。我到处寻找编译器添加的确切样板,但似乎找不到(除了说明它确实生成了这样的样板)。我不止一次地看了那个文件,一定是忽略了那个部分。看看这一点,很明显为什么这不起作用,也不能起作用。我认为这段代码不起作用。传递参数的语法是什么?
import groovy.transform.CompileStatic

@CompileStatic
abstract class StaticBase extends Script {
    StaticBase() {
    }

    StaticBase(Binding binding) {
        super(binding)
    }

    String[] getArgs() {
        (String[]) getBinding().getVariable("args")
    }
}
groovyc --configscript config.groovy -b StaticBase test.groovy
java -cp .;%GROOVY_HOME%\lib\groovy-2.5.3.jar test 1 2