我写了一个小的Groovy脚本(只有几个简单的指令),并将其命名为a-b.groovy
。
我的同事无法运行它,说:
我认为在Groovy脚本文件名中“-”是非法的。
问题:哪些字符是Groovy文件名中非法的?
(注意:与Groovy脚本文件的命名约定不同,我的问题不是关于命名约定的)
我写了一个小的Groovy脚本(只有几个简单的指令),并将其命名为a-b.groovy
。
我的同事无法运行它,说:
我认为在Groovy脚本文件名中“-”是非法的。
问题:哪些字符是Groovy文件名中非法的?
(注意:与Groovy脚本文件的命名约定不同,我的问题不是关于命名约定的)
groovy.lang.Script
类的Java类。它的名称取自Groovy脚本文件名。看一个例子:someSimpleGroovyScript.groovy。println "test"
当我们使用groovyc someSimpleGroovyScript.groovy
编译它时,我们会看到一个名为someSimpleGroovyScript.class
的类文件。现在让我们看看这个类是什么样子的:
javap someSimpleGroovyScript
Compiled from "someSimpleGroovyScript.groovy"
public class someSimpleGroovyScript extends groovy.lang.Script {
public static transient boolean __$stMC;
public someSimpleGroovyScript();
public someSimpleGroovyScript(groovy.lang.Binding);
public static void main(java.lang.String...);
public java.lang.Object run();
protected groovy.lang.MetaClass $getStaticMetaClass();
}
尽管Java类命名标准适用于Groovy脚本名称,但有一些边缘情况Groovy支持。
-
字符您可以将脚本命名为a-b.groovy
并作为Groovy脚本运行:
groovy a-b.groovy
你甚至可以使用groovyc
编译它,得到以下的Java类:
Compiled from "a-b.groovy"
public class a-b extends groovy.lang.Script {
public static transient boolean __$stMC;
public a-b();
public a-b(groovy.lang.Binding);
public static void main(java.lang.String...);
public java.lang.Object run();
protected groovy.lang.MetaClass $getStaticMetaClass();
}
尽管这个类名对于Java编译器来说不正确,但你仍然可以使用Java运行它(你需要将groovy-all
添加到类路径中):
java -classpath ".:./groovy-all-2.4.12.jar" a-b
$
Groovy 中你甚至可以将你的脚本命名为 123$.groovy
,然后直接运行它:
groovy 123\$.groovy
然而,Groovy编译器在将此脚本编译为Java类时会将$
替换为下划线:
javap 123_
输出:
Compiled from "123$.groovy"
public class 123_ extends groovy.lang.Script {
public static transient boolean __$stMC;
public 123_();
public 123_(groovy.lang.Binding);
public static void main(java.lang.String...);
public java.lang.Object run();
protected groovy.lang.MetaClass $getStaticMetaClass();
}
您仍然可以使用Java运行这样编译的脚本:
java -classpath ".:./groovy-all-2.4.12.jar" 123_
您也可以在脚本名称中使用空格,例如this is script.groovy
可以执行以下命令:
groovy this\ is\ script.groovy
Groovy编译器将用下划线替换每个空格:
Compiled from "this is script.groovy"
public class this_is_script extends groovy.lang.Script {
public static transient boolean __$stMC;
public this_is_script();
public this_is_script(groovy.lang.Binding);
public static void main(java.lang.String...);
public java.lang.Object run();
protected groovy.lang.MetaClass $getStaticMetaClass();
}
java -classpath ".:./groovy-all-2.4.12.jar" this_is_script
class.groovy
作为脚本名称更进一步,您可以创建一个名为class.groovy
的脚本,它将编译成以下Java类:
Compiled from "class.groovy"
public class class extends groovy.lang.Script {
public static transient boolean __$stMC;
public class();
public class(groovy.lang.Binding);
public static void main(java.lang.String...);
public java.lang.Object run();
protected groovy.lang.MetaClass $getStaticMetaClass();
}
javac
编译器不允许您编译具有此名称的类,但是java
在运行此字节码时没有任何问题:
java -classpath ".:./groovy-all-2.4.12.jar" class
我遇到了一个奇怪的问题,这个脚本包含一个带有破折号的文件名和一个函数,该函数将 Closure
作为参数。
让我们考虑这个例子,test-script.groovy
:
#!/usr/bin/env groovy
void foo(String msg, Closure clo)
{
println msg
clo()
}
foo 'bar', { -> println 'closure-bar'}
在我的开发环境中,使用 Groovy 2.4.16
它能够完美运行,它会输出:
bar
closure-bar
Caught: java.lang.ClassFormatError: Illegal class name "test-script$foo" in class file test-script$foo
java.lang.ClassFormatError: Illegal class name "test-script$foo" in class file test-script$foo
at test-script.run(test-script.groovy:9)
如果我将test-script.groovy
重命名为testScript.groovy
,它可以在2.4.16和2.4.5版本中工作。
我追踪到这个"错误修复"是在Groovy 2.4.15
版本中修复的。在此版本之前,它无法正常工作。
这个版本的changelog没有显示任何相关的修复,所以可能已经被包含在其他的错误修复中了。
无论如何,我已经卡了几个小时在这个问题上,如果能帮助到其他人,那就太好了!