Groovy语法是Java语法的精确超集吗?

33
作为一名Java程序员,我并没有很深入了解Groovy,但是最近在使用GMaven扩展Maven时经常使用Groovy。到目前为止,在Groovy中我可以使用所有需要的Java代码,并且还有额外的Groovy语法(元类方法、更多操作符、闭包)。我对Groovy的了解还远远不够,但我喜欢它,特别是用于脚本编写(我对于在企业环境中使用非静态类型语言有些谨慎,但这不是本话题)。
无论如何,问题是: 每一段有效的Java代码都能自动成为有效的Groovy代码吗?(我所说的是源代码,而不是编译后的类,我知道Groovy可以与Java类交互。)或者说,是否有些Java结构在Groovy中是不合法的?可能会存在一个被保留作为Java标识符的Groovy关键字,或者其他什么情况?或者说,Groovy是否被故意设计为与Java 100%的源代码兼容?

1
可能是Valid Java code that is NOT valid Groovy code?的重复问题。 - Michael Borgwardt
1
@Michael 我同意这是一个重复问题,但另一个问题已经超过一年了(至少自那时起groovy已经有了重大更新)。是否有关于问题有效期的一般政策? - Sean Patrick Floyd
可能是 Groovy 是 Java 的超集吗? 的重复问题。 - starcorn
4个回答

23

不是的。以下是Groovy中的关键字,而不是Java:

any    as     def    in     with

此外,虽然不是关键字,但是delegateowner在闭包中具有特殊含义,如果不小心可能会让你陷入困境。

此外,在语言语法方面也存在一些细微差异。例如,在声明中,Java对数组方括号的位置更加灵活:

public static void main(String args[]) // valid java, error in groovy

Groovy的解析方式也不同。这里有一个示例:

public class Test {
    public static void main(String[] args) {
        int i = 0;
        i = 5
        +1;
        System.out.println(i);
    }
}

Java会打印6,groovy会打印5。

虽然groovy在很大程度上与java兼容,但还有许多情况是不同的。尽管如此,它非常兼容人们实际编写的代码。


1
啊,行尾结束语句(例如在JavaScript中造成许多可怕的错误)。感谢提示(+1)。 - Sean Patrick Floyd
5
Java中的String args[]表示法很糟糕(让我想起了我对C语言所有讨厌的事情)。很高兴听说Groovy没有这个。 - Sean Patrick Floyd
Java中的String[] args标记很糟糕(让我想起了我讨厌Java的所有事情)。很遗憾,看到Groovy不支持另一种方式... :( - paulotorrens

17

它不是。

我最喜欢的不兼容性:字面数组:

String[] s = new String[] {"a", "b", "c"};

在Groovy中,此处大括号应包含闭包而不是字面数组。


2
那么 Groovy 版本将是 String[] s = ["a", "b", "c"]; 吗? - Sean Patrick Floyd
有没有一种在Groovy中实现的方法?我的意思是:拥有一个真正的数组,而不是列表。 - Rekin
2
差不多。[] 语法创建了一个列表。但是如果你在末尾加上 "as String[]",那么它就会成为一个字符串列表。 - Goran Jovic
4
当你声明类型时,在这个例子中不需要使用 asString[] arr = [ 'a', 'b', 'c' ] 就足够了。 - tim_yates
2
在这种情况下,接受一个答案并不容易,因为它们都很好,没有一个正确的答案。所以我选择给Goran打勾,因为他的声望最低。 - Sean Patrick Floyd
显示剩余2条评论

12

3
谢谢。其中一个例子是,Groovy不支持do...while循环结构,这也是件好事。我开始有这样一种印象:Groovy从Java中汲取了所有好的东西,却省略了所有糟糕的东西。这也引出了一个明显的问题:Groovy是否有循环标签? - Sean Patrick Floyd
是的,循环标签在其中,因此 continue labelbreak label 是有效的 Groovy。 - tim_yates

5

已经有人举例说明了在Groovy中不合法的Java语法(例如文字数组)。也值得记住的是,在两种语言中都合法的一些语法并不意味着在两种语言中具有相同的含义。例如,在Java中:

foo == bar

测试对象是否相同,即foobar是否都指向同一个对象?在Groovy中,这是测试对象相等性的方法,即它返回foo.equals(bar)的结果。


1
我知道,这是 Groovy 中一个可怕的特性,以我的观点来看。幸运的是,在 Java 中我几乎从不依赖 ==(非原始类型),所以在 Groovy 中我也不会犯这个错误。 - Sean Patrick Floyd
8
我不同意。我认为这是一个好的特性。测试相等性更常见,不依赖于不太直观的身份概念。而且,对象编写者可以通过覆盖 equals() 方法完全控制它。测试身份由语言严格定义,并暴露了丑陋的Java不一致性,如 new Long(1) != new Long(1) 但是 Long.valueOf(1) == Long.valueOf(1) 。Groovy 使用运算符(可读性强、直观)来进行“好”的情况,使用方法调用(标记为需要注意的异常情况)来进行“坏”的情况。Java 则相反。 - ataylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接