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

时间:2009-03-26 21:26:24

标签: java grails groovy

大多数Java代码也是语法上有效的Groovy代码。但是,有一些例外情况引起了我的疑问:

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

更新

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

  1. 数组初始化
  2. 内部课程
  3. def是Groovy中的关键字,但不是Java
  4. "$$" - 字符串 - 在Groovy中解析为无效的GString
  5. 非静态初始化块-- class Foo { Integer x; { x = 1; } }
  6. 这是完整的清单吗?还有其他例子吗?

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

8 个答案:

答案 0 :(得分:33)

以下是有效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 list-literal语法:

@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字符串实习,它似乎有时会起作用。

这个例子太长了,无法添加到现有答案中,但重点是 语法有效的Java代码,因为Groovy在运行时可能会有不同的行为

要获得与两个非空对象的Java x == y相同的结果,您需要在Groovy中使用x.is(y)x == y是有效的Groovy,只是执行不同的操作

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

答案 1 :(得分:12)

好的,还有一点:

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支持这两者,但并不完全。

答案 2 :(得分:3)

多维数组,其中未指定大小。

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

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

答案 3 :(得分:2)

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时,方法可能返回错误的(无效)结果。

答案 4 :(得分:1)

我现在能想到的只有:

  • int def;
  • String s = "$$";

答案 5 :(得分:1)

有没有人提到==的区别?我拿这个来自Grails文档。

==表示所有类型的等号。在Java中,语法中有一个奇怪的部分,其中==表示基本类型的相等性,==表示对象的标识。

答案 6 :(得分:1)

在变量名而不是类型之后使用[]声明给定类型的数组在Java中工作但不在Groovy中工作。

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

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

Primitive类型文字的结果:byte不能用作方法名称

答案 7 :(得分:0)

非静态初始化块:

class Foo {
  Integer x;   
  { x = 1; }
}

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