Groovy版本:2.4.5 JVM:1.8.0_151供应商:Oracle Corporation操作系统:Linux
我尝试了Groovy程序的两个版本。如果程序中没有其他内容,则运行“示例”类(例如,没有“ println“ Test”')。
如果我有一个“ println”语句,为什么Example类不能运行?
class Example {
static void main(String[] args) {
def clos = {println "Hello World"};
clos.call();
}
}
println "Test"
我希望上面的程序在运行时可以打印出来:
Hello World
测试
当类外还有另一行时,为什么类不执行?
答案 0 :(得分:5)
您需要注意一些事项。当您创建具有以下内容的脚本(我们将其称为someScript.groovy
)
#!groovy
println "Test"
println 21 + 21
它被编译为以下类:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import groovy.lang.Binding;
import groovy.lang.Script;
import org.codehaus.groovy.runtime.InvokerHelper;
public class someScript extends Script {
public someScript() {
}
public someScript(Binding context) {
super(context);
}
public static void main(String... args) {
InvokerHelper.runScript(someScript.class, args);
}
public Object run() {
((someScript)this).println("Test");
Object var10000 = null;
((someScript)this).println(21 + 21);
return null;
}
}
如您所见,Groovy脚本的主体在生成的类中表示为方法run()
。当我们在脚本中添加一个类时,假设您的问题中的Example
类,run()
方法的主体完全没有改变-该类被编译为一个Example.class
字节码文件就是这样:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import groovy.lang.Closure;
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.codehaus.groovy.runtime.GeneratedClosure;
public class Example implements GroovyObject {
public Example() {
MetaClass var1 = this.$getStaticMetaClass();
this.metaClass = var1;
}
public static void main(String... args) {
class _main_closure1 extends Closure implements GeneratedClosure {
public _main_closure1(Object _outerInstance, Object _thisObject) {
super(_outerInstance, _thisObject);
}
public Object doCall(Object it) {
DefaultGroovyMethods.println(Example.class, "Hello World");
return null;
}
public Object call(Object args) {
return this.doCall(args);
}
public Object call() {
return this.doCall((Object)null);
}
public Object doCall() {
return this.doCall((Object)null);
}
}
Closure clos = new _main_closure1(Example.class, Example.class);
clos.call();
}
}
当我们运行Groovy编译器来编译someScript.groovy
(groovyc someScript.groovy
)并列出生成的类时,我们将看到以下内容:
ls -lh *.class
-rw-rw-r--. 1 wololock wololock 2,0K 12-07 10:26 Example.class
-rw-rw-r--. 1 wololock wololock 1,6K 12-07 10:26 'Example$_main_closure1.class'
-rw-rw-r--. 1 wololock wololock 1,4K 12-07 10:26 someScript.class
注意:此
Example$_main_closure1.class
代表Example.main()
方法中使用的闭包
现在,让我们看看如果从println
文件中注释(或删除)someScript.groovy
语句并进行编译会发生什么情况:
someScript.groovy
#!groovy
class Example {
static void main(String[] args) {
def clos = {println "Hello World"};
clos.call();
}
}
//println "Test"
//
//println 21 + 21
编译时间:
> groovyc someScript.groovy
> ls -lh *.class
-rw-rw-r--. 1 wololock wololock 2,0K 12-07 10:31 Example.class
-rw-rw-r--. 1 wololock wololock 1,6K 12-07 10:31 'Example$_main_closure1.class'
如您所见,没有生成someScript.class
类文件。发生这种情况是因为我们刚刚编译的脚本文件不包含任何正文,但其中包含Example
类。当您运行这样的脚本时,Groovy会尝试找到第一个静态main()
方法来执行它-这就是为什么运行以下脚本会产生Hello World
输出的原因:
> groovy someScript.groovy
Hello World
让我们走得更远,在someScript.groovy
文件的顶部添加另一个类:
someScript.groovy
#!groovy
class Foo {
static void main(String[] args) {
println "Bar"
}
}
class Example {
static void main(String[] args) {
def clos = {println "Hello World"};
clos.call();
}
}
//println "Test"
//
//println 21 + 21
脚本主体仍被注释掉。让我们编译一下,看看生成了什么类文件:
> groovyc someScript.groovy
> ls -lh *.class
-rw-rw-r--. 1 wololock wololock 2,0K 12-07 10:35 Example.class
-rw-rw-r--. 1 wololock wololock 1,6K 12-07 10:35 'Example$_main_closure1.class'
-rw-rw-r--. 1 wololock wololock 1,8K 12-07 10:35 Foo.class
正如预期的那样,我们可以看到3个类文件。让我们看看如果使用groovy
命令运行脚本会发生什么情况:
> groovy someScript.groovy
Bar
现在您可以看到Foo.main()
方法已执行,因为Groovy将此方法放在脚本文件的顶部,并且假定这是我们要运行的主要方法。
让我们用包含两个类和脚本主体的示例来完成此操作:
someScript.groovy
#!groovy
class Foo {
static void main(String[] args) {
println "Bar"
}
}
class Example {
static void main(String[] args) {
def clos = {println "Hello World"};
clos.call();
}
}
println "Test"
println 21 + 21
编译时间:
> groovyc someScript.groovy
> ls -lh *.class
-rw-rw-r--. 1 wololock wololock 2,0K 12-07 10:39 Example.class
-rw-rw-r--. 1 wololock wololock 1,6K 12-07 10:39 'Example$_main_closure1.class'
-rw-rw-r--. 1 wololock wololock 1,8K 12-07 10:39 Foo.class
-rw-rw-r--. 1 wololock wololock 1,4K 12-07 10:39 someScript.class
这一次是因为脚本主体不为空而生成了类someScript
。最后查看生成的someScript.class
文件:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import groovy.lang.Binding;
import groovy.lang.Script;
import org.codehaus.groovy.runtime.InvokerHelper;
public class someScript extends Script {
public someScript() {
}
public someScript(Binding context) {
super(context);
}
public static void main(String... args) {
InvokerHelper.runScript(someScript.class, args);
}
public Object run() {
((someScript)this).println("Test");
Object var10000 = null;
((someScript)this).println(21 + 21);
return null;
}
}
如您所见,与我们的第一个示例相比(脚本中没有类,只有两个println语句),它没有改变,因此除了运行someScript.run()
方法外,我们别无他求即将发生。让我们运行脚本:
> groovy someScript.groovy
Test
42
scriptName.run()
方法,然后将其执行。main()
方法的类添加到Groovy脚本中并保留脚本主体,则添加的类main()
方法将不会执行-它只能编译该类,并且可以使用如果需要,可以在脚本主体中显式显示它。main()
方法的类添加到Groovy脚本中,并且没有放置任何脚本主体(该类之外的任何语句/表达式),则Groovy将搜索第一个静态main()
方法,并执行它。