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

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

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

更新:

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

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

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

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

【问题讨论】:

    标签: java grails groovy


    【解决方案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
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-02-11
          • 2010-09-09
          • 1970-01-01
          • 2011-10-19
          相关资源
          最近更新 更多