有效的 Java 代码不是有效的 Groovy 代码?

Posted

技术标签:

【中文标题】有效的 Java 代码不是有效的 Groovy 代码?【英文标题】:Valid Java code that is NOT valid Groovy code? 【发布时间】:2010-10-15 19:32:53 【问题描述】:

大多数 Java 代码也是语法上有效的 Groovy 代码。但是,有一些例外情况导致我提出我的问题:

Java 中的哪些构造/特性在 Groovy 中在语法上是无效的? 请提供不是有效 Groovy 代码 (Groovy 1.6) 的 Java 代码 (Java 1.6) 的具体示例。

更新:

到目前为止,我们已经得到了五个语法上有效的 Java 代码示例,这些示例不是有效的 Groovy 代码:

    数组初始化 内部类 def 在 Groovy 中是关键字,但在 Java 中不是 "$$"-strings - 在 Groovy 中被解析为无效的 GStrings 非静态初始化块-- class Foo Integer x; x = 1;

这是完整的列表吗?还有其他例子吗?

更新 #1: 我已经开始悬赏来解决这个问题。赏金将授予提供最全面示例列表的人。到目前为止,我们已经发现了五个例子,但我敢肯定还有更多的例子。所以让他们来吧!

【问题讨论】:

【参考方案1】:

这里列出了有效的 Java 6,但无效的 Groovy 1.6。这不是一个完整的列表,但我认为它涵盖了大多数情况。其中一些是更高版本的 Groovy 允许的,如下所述。

(顺便说一句,我认为您应该注意,非静态初始化块确实可以在 Groovy 中工作。)

Groovy 1.6 (1.7 added inner classes) 中的任何内部类声明:

包括静态,

public class Outer
  static class Inner

非静态的,

public class Outer
  class Inner

本地类,

public class Outer
  public static void main(String[] args) 
    class Local  
  

和匿名类

java.util.EventListener listener=new java.util.EventListener();

将 Groovy 关键字用作变量在任何 Groovy 版本中都不起作用:

int def;
int in;
int threadsafe;
int as;

Java 数组初始化

String[] stuff=new String[]"string";
int[] array=1,2,3;

通过将... 更改为[...] 来使用Groovy 数组文字格式。

在后面的不是有效表达式的字符串中使用美元符号

String s="$$";
String s="$def";
String s="$enum";
String s="$;";
String s="$\\";
//etc.

for 循环中有多个初始化器

for (int i=0, j=0; i < 5; i++) 

for 循环中有多个增量

int j=0;
for (int i=0; i < 5; i++,j++) 

使用换行符分解一些表达式

int a= 2 
/ 2 
;

提示:在 Groovy 中使用反斜杠续行

int a= 2 \
/ 2 \
;

以没有主体的情况结束切换

switch(a)
  case 1:

在没有主体的开关中具有默认值

适用于默认位于末尾的两种情况

int a=0;
switch(a)
    default:

或者在中间的某个地方

switch(a)
    default:
    case 1:
        break;

带有列表的注释

@SuppressWarnings("boxing","cast")

提示:改用 Groovy 列表文字语法:

@SuppressWarnings(["boxing","cast"])

本机方法声明

public native int nativeMethod();

**1.6 中每个枚举的类(在以后的 Groovy 版本中有效)**

public enum JavaEnum
  ADD
    public String getSymbol() return "+"; 
  ;
  abstract String getSymbol();

循环

do
  System.out.println("stuff");
while(true);

平等

虽然从技术上讲 == 是有效的 Groovy 和 Java,但它在语义上是不同的。这是您不能仅仅依靠将 Java 编译为 Groovy 而不进行更改的原因之一。更糟糕的是,由于 Java 字符串实习,它有时似乎可以工作。

该示例太长,无法添加到现有答案中,但重点是 语法上作为 Groovy 有效的 Java 代码在运行时可能会表现不同

要获得与 Java 的 x == y 相同的结果,对于两个非空对象,您需要在 Groovy 中使用 x.is(y)x == y 是有效的 Groovy,它只是做了一些不同的事情

The Groovy documentation has a more detailed and broader list of differences.

【讨论】:

看起来内部类示例不再有效; Groovy 现在支持内部类。见groovy-lang.org/…。其他一些需要对 Groovy 列表语法进行简单的更改,但用 Java 形式编写的绝对无效。【参考方案2】:

好的,这里有一点:

int[] i =  0, 1, 2 ;

这在 java 中是好的语法,在 groovy 中不好。

我认为您不想假设任何给定的 java 代码在 groovy 中都是等效的。 This site 描述了一些差异,其中包括基本的东西 == 在两种语言中并不意味着相同的东西。另外,静态数组初始化不同,没有匿名内部类。

这在 Java 1.6 中编译得很好

public class Test2 
    int[] i =  0, 1, 2 ;

    private class Class1 
        public void method1() 
            if (i[2] == 2) 
                System.out.println("this works");
            
        
    

    public void method1() 
        Class1 class1 = new Class1();
        class1.method1();
    

但是在 Groovy 中是错误的。它在 Groovy 1.6 中给出了以下错误:

unexpected token: 1 @ line 2, column 14.

Class definition not expected here. Possible attempt to use inner class. Inner classes not supported, perhaps try using a closure instead. at line: 4 column: 2.

如果你修复了这些问题,它会打印出你期望的结果。

如果您正在寻找较新的语言语法问题,例如泛型或注释,Groovy 支持这两者,但不完全支持。

【讨论】:

投反对票的不是我,但是:这不是被问到的。没有人说 Java 代码在 groovy 中是等价的。问题是在 Groovy 中哪些语法上有效的 Java 代码在语法上无效。 我不会这样解释这个问题:“Groovy 不支持 Java 中的哪些构造/功能?”我读到的行为不同。也许这个问题需要更清楚。【参考方案3】:

多维数组,未指定大小。

def x=new Object[5][];  // ERROR: expression expected 

def x=new Object[5][2]; // this works

【讨论】:

从外观上看,这在以后的 Groovy 版本中得到了支持。【参考方案4】:

补充 Peter Dolberg 的回答:

除了在 Groovy 中无效的有效 Java 代码之外,您还需要警惕在 Java 和 Groovy 中都有效但在 Groovy 中产生不同结果的代码。明显的例子是 char 字面量和 GStrings:

System.out.println(String.valueOf('3' + 3)); // 54 in Java, 33 in Groovy (arithmetic ascii value vs. String concat)

System.out.println("$3+4");

隐式访问器:

class Foo public static int counter; public static int bar; public static void getBar() counter++; return bar;
System.out.println(Foo.bar);
System.out.println(Foo.counter); // 0 in Java, 1 in Groovy

toString() 已被 GroovyDefaultMethods 覆盖,当您解析结果时可能会咬到您。

Map someMap = new HashMap();
someMap.put("a", "b")
someMap.toString();

等号操作

"foo" == "foo"
class Foo public boolean equals() return true;
new Foo() == new Foo()

一些运算符优先级:

a *= b/100; // Groovy: (a *= b)/100; Java: a *= (b/100);

这不是对原始问题的正确答案,因为 groovy 代码本身在语法上仍然有效,但由于它具有不同的结果,我认为值得在这里提一下。结果是,从算法上讲,一个方法在从 Java 复制到 Groovy 时可能会返回错误(无效)的结果。

【讨论】:

平等绝对是个大陷阱【参考方案5】:

暂时能想到的:

int def; String s = "$$";

【讨论】:

【参考方案6】:

有没有人提到 == 的区别?这是我从 Grails 文档中获取的。

== 表示所有类型都相等。在 Java 中,有一个奇怪的语法部分,其中 == 表示原始类型的相等,而 == 表示对象的标识。

【讨论】:

【参考方案7】:

在变量名后使用 [] 代替类型声明给定类型的数组在 Java 中有效,但在 Groovy 中无效。

byte[] buff = new byte[1024]; // Works

byte buff[] = new byte[1024]; // Not Groovy

原始类型文字的结果:字节不能用作方法名称

【讨论】:

【参考方案8】:

非静态初始化块:

class Foo 
  Integer x;   
   x = 1; 

更新:这实际上是有效的 Groovy 代码。

【讨论】:

见鬼?我也不知道那是有效的 Java。 测试确认它确实在创建类的实例时运行。怪异的。你知道的越多。 这在 Groovy 中有效。至少它适用于 Groovy 1.5.7 和 1.6。 嗯,它也对我有用。我可以发誓这过去是行不通的。哦,好吧,否决答案。 值得一票;有些人不知道这适用于 Java,您纠正说这实际上也适用于 Groovy。 :3

以上是关于有效的 Java 代码不是有效的 Groovy 代码?的主要内容,如果未能解决你的问题,请参考以下文章

获得使用 Java 或 Groovy 填充的有效 oauth_signature 的绝对最少代码?

Groovy文件检查

如何自动将 Java 代码转换为 Groovy 代码 [关闭]

Groovy/Spock 测试导论

Groovy循环控制 ( Java 语法循环 | 默认的 IntRange 构造函数 | 可设置翻转属性的 IntRange 构造函数 | 可设置是否包含 to 的构造函数 | 0..9 简写 )(代

GMavenPlus:Groovy 到 JAR - 无法找到或加载主类。主类存在,清单文件显示有效