使用命令行参数

时间:2017-07-12 10:21:07

标签: groovy compilation command-line-arguments

我正在尝试静态编译一个groovy脚本来加速它的执行,但是如果使用命令行参数则无法使它工作。我的实际脚本要长得多,但我用于此问题的单行脚本完美地再现了我的错误。

使用以下脚本( test.groovy

println(args.length)

这可以使用命令groovyc test.groovy进行编译,并通过java命令java -cp .;%GROOVY_HOME%\lib\* test运行,并且只打印使用的命令行参数的数量。

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

withConfig(configuration) {
    ast(groovy.transform.CompileStatic)
}

并使用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

当我尝试静态编译时,才会出现此错误。我可以通过将脚本包装在一个类中并将我的代码放在一个main方法(当然,这是编译器用脚本执行的操作)来实现它,但是当我尝试使用脚本时(不是我喜欢做什么)。出于某种原因,静态编译时变量 args 是未知的。我已经尝试this.args但仍然收到错误。如果我尝试为args(String[] args)声明一个类型,它就不再接收命令行参数。

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

我在Windows 7上使用带有Java 8的Groovy版本2.4.10。

2 个答案:

答案 0 :(得分:2)

执行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注释,我们将得到未声明变量的错误。

因此,您必须在类中包装代码才能使用静态编译。

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

答案 1 :(得分:2)

该脚本通过对绑定对象的动态评估来工作。如果要使用静态编译,则需要使用显式形式,将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)