25

Most Java code is also syntactically valid Groovy code. However, there are a few exceptions which leads me to my question:

Which constructs/features in Java are syntactically invalid in Groovy? Please provide concrete examples of Java code (Java 1.6) that is NOT valid Groovy code (Groovy 1.6).

Update:

So far we've got five examples of syntactically valid Java code that is not valid Groovy code:

  1. Array initializations
  2. Inner classes
  3. def is a keyword in Groovy, but not in Java
  4. "$$"-strings - parsed as an invalid GStrings in Groovy
  5. Non-static initialization blocks -- class Foo { Integer x; { x = 1; } }

Is this the complete list? Any further examples?

Update #1: I've started a bounty to bump this question. The bounty will be granted to the person who provides the most comprehensive list of examples. So far we've uncovered five examples, but I'm sure there a quite some more out there. So keep them coming!

Zach Lysobey
  • 14,959
  • 20
  • 95
  • 149
knorv
  • 49,059
  • 74
  • 210
  • 294

8 Answers8

35

Here is a list of items that are valid Java 6, but not valid Groovy 1.6. This isn't a complete list, but I think it covers most of the cases. Some of these are permitted by later Groovy versions as noted below.

(By the way, I think you should note that non-static initialization blocks DO work in Groovy.)

Any inner class declaration in Groovy 1.6 (1.7 added inner classes):

including static,

public class Outer{
  static class Inner{}
}

non-static,

public class Outer{
  class Inner{}
}

local classes,

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

and anonymous classes

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

Using Groovy keywords as variables won't work in any Groovy version:

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

Java array initialization

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

Use the Groovy array-literal format by changing {...} to [...].

Using dollar signs in strings where what follows isn't a valid expression

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

More than one initializer in a for loop

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

More than one increment in a for loop

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

Breaking up some expressions using newlines

int a= 2 
/ 2 
;

Hint: use a backslash line-continuation in Groovy

int a= 2 \
/ 2 \
;

Ending switch with a case that has no body

switch(a){
  case 1:
}

Having a default in a switch with no body

Applies in both cases where default is at the end

int a=0;
switch(a){
    default:
}

or somewhere in the middle

switch(a){
    default:
    case 1:
        break;
}

Annotations with lists

@SuppressWarnings({"boxing","cast"})

Hint: use Groovy list-literal syntax instead:

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

Native method declaration

public native int nativeMethod();

**Class per enum in 1.6 (valid in later Groovy versions) **

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

Do loop

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

Equality

While technically == is valid Groovy and Java, it's semantically different. It's one of the reasons you can't rely on just compiling Java as Groovy without changes. Worse, it might seem to work sometimes due to Java string interning.

The example was too long to add to an existing answer, but the point is that Java code that's syntatically valid as Groovy might behave differently at runtime.

To get the same result as Java's x == y for two not-null objects you need x.is(y) in Groovy. x == y is valid Groovy, it just does something different.

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

Craig Ringer
  • 307,061
  • 76
  • 688
  • 778
Peter Dolberg
  • 2,027
  • 16
  • 21
  • It looks like the inner class example is no longer valid; Groovy supports inner classes now. See http://groovy-lang.org/differences.html#_creating_instances_of_non_static_inner_classes . Some of the others need a simple change to Groovy list-syntax, but are definitely invalid as written in Java form. – Craig Ringer Nov 07 '18 at 01:23
12

Ok, heres one point:

int[] i = { 0, 1, 2 };

That is good syntax in java, bad in groovy.

I don't think you want to assume any given java code will be equivalent in groovy. This site describes some of the differences, which includes things as basic as == not meaning the same thing in both languages. Also, static array initialization is different, and there are no anonymous inner classes.

This compiles fine in 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();
    }
}

But is so wrong in Groovy. It gives the following errors in 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.

If you fix those things, it does print what you expect, though.

If you're looking for newer language syntax issues, like generics or annotations, Groovy supports both of those, though not fully.

Brandon V
  • 5
  • 2
  • 2
John Ellinwood
  • 14,291
  • 7
  • 38
  • 48
  • It wasn't me who downvoted, but: that's not what was asked. Nobody said Java code would be equivalent in groovy. The question was what snytactically valid Java code is not syntactically valid in Groovy. – Michael Borgwardt Mar 26 '09 at 22:19
  • I do not interpret the question that way: "Which constructs/features in Java are not supported in Groovy?" I read that as behave differently. Perhaps the question needs to be clearer. – TofuBeer Mar 26 '09 at 22:21
3

Multidimensional arrays, where size is not specified.

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

def x=new Object[5][2]; // this works
user339047
  • 399
  • 1
  • 5
2

Complementing the answer by Peter Dolberg:

Besides valid Java code that is not valid in Groovy, you also need to be wary of code that is valid in both Java and Groovy, but has different results in Groovy. Obvious examples are char literals and 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}");

Implicit accessors:

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() has been overwritten by GroovyDefaultMethods, which can bite you when you parse the result.

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

The equals operation

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

Some operator precedence:

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

This is not a correct answer to the original question, since the groovy code is still syntactically valid in itself, but since it has a different result, I think it is worthwhile mentioning it here. The result is that algorithmically, a method may return the wrong(invalid) result when copied from Java to Groovy.

tkruse
  • 10,222
  • 7
  • 53
  • 80
1

Has anyone mention the difference in ==? I took this is from Grails documentation.

== means equals on all types. In Java there's a wierd part of the syntax where == means equality for primitive types and == means identity for objects.

Joe
  • 1,219
  • 8
  • 13
1

Declaring an array of a given type using [] after the variable name instead of the type works in Java but not Groovy.

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

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

Results in Primitive type literal: byte cannot be used as a method name

DSoa
  • 663
  • 8
  • 19
1

All I can think of for now:

  • int def;
  • String s = "$$";
Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
0

Non-static initialization blocks:

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

UPDATE: This is in fact valid Groovy code.

Jen S.
  • 4,106
  • 4
  • 35
  • 44