
Update: fixed the embarrassing label (s/Scala/JavaFx/)
Feature | Java | Groovy | JavaFx |
---|---|---|---|
Type System | Static with few dynamic checks inserted as needed. | Dynamic, optional static types. | Static, with type inference. (chapter 4) |
Comments |
/* * multiline comment */ /** * javadoc comment */ // single line comment |
/* * multiline comment */ /** * groovydoc comment */ // single line comment |
/* * multiline comment */ /** * javafxdoc comment */ // single line comment |
End of statement | ; | a new line will do most in most cases. Use ; when ambiguous | ; |
Control Statements - if |
if (condition) { // statements } if (condition) { // statements } else if (condition) { // statements } else { // statements } |
if (condition) { // statements } if (condition) { // statements } else if (condition) { // statements } else { // statements } note: if may return a value in a future version of Groovy. |
if (condition) { // expression } if (condition) { // expression } else if (condition) { // expression } else { // expression } note: if is an expression, not an statement, so it returns a value. |
Control Statements - ternary operator | (condition) ? true_statement : false_statement |
(condition) ? true_statement : false_statement
Elvis operator, a refinement over the ternary operator. If the condition expression is true then said condition expression will be the true_statement condition ?: false_statement |
if (condition) true_expression else false_expression |
Control Statements - while |
while (condition) { // statements } do { // statements } while (condition); |
while (condition) { // statements } |
while (condition) { // expressions } note: curly braces are always required around the body |
Control Statements - for |
for (init; condition; increment ) { // statements } for (Type t: iterable ) { // statements } |
for (init; condition; increment ) { // statements } for (Type t: iterable ) { // statements } for ( variable in iterable ) { // statements } Every single object in Groovy is iterable, default impl returns the object itself |
for ( e in sequence ) { // statements } a for loop may accept related sequences for (album in albums, track in album.tracks) { if (album.title == track) // do x else // do y } they also accept filters (with a where clause) |
Control Statements - switch |
switch (target) { case constant_expr: // statements [break] ... default: // statements } |
switch (target) { case constant_expr: // statements [break] ... default: // statements } * target may be any object * case statements may use same expressions as in Java plus Strings, Matchers, regular expression, closures, ranges, any object that supports isCase()
|
Not supported |
Control Statements - conditions | conditions must be evaluated in a boolean context |
conditions may be evaluated in many contexts,
this is known as the Groovy Truth, some rules
follow (this is not a complete set, please
refer to Groovy in Action or Groovy's site)
evaluates to false
|
same as Java |
String Literals | "Hello Java" |
"Hello Groovy" // double quote 'Hello Groovy' // single quoute """Hello Groovy""" // multiline // variable interpolation name = "Groovy" "Hello ${name}" // evals to Hello Groovy |
"Hello JavaFx" // double quote 'Hello JavaFx' // single quoute "Hello JavaFx" // multiline (both single and double quote work) // variable interpolation var name = "JavaFx" "Hello {name}" // evals to Hello JavaFx |
Class declaration |
class HelloWorld { // fields // methods } |
class HelloWorld { // fields // methods } |
class HelloWorld { // attributes // functions } |
Instance Fields |
[access_modifier] Type name where access_modifier is any of
|
[access_modifier] Type name where access_modifier is any of
class Person { String name } Is equivalent to the following Java class public class Person { private String name; public void setName( String name ) { this.name = name; } public String getName() { return name; } } |
[access_modifier] attribute name [:Type] where access_modifier is any of
Haven't seen access modifiers in blog examples, assuming they work the same as in Java |
Class Fields (static) |
[access_modifier] static Type name where access_modifier is any of
|
[access_modifier] static Type name where access_modifier is any of
|
[access_modifier] static attribute name [:Type] where access_modifier is any of
|
Global Variables | Not supported. Every field/constant must belong to a class | Supported only in scripts, otherwise follows Java rules | Not supported. Every field/constant must belong to a class |
Method definition |
class Person { [access_modifier] Type name() { // statements } } where access_modifier is any of
|
class Person { [access_modifier] Type name() { // statements } } where access_modifier is any of
|
class Person { [access_modifier] function name() [:Type] = { // expressions } } where access_modifier is any of
|
Static Method Definition |
class Person { [access_modifier] static Type name() { // statements } } where access_modifier is any of
|
class Person { [access_modifier] static function name() [:Type]{ // statements } } where access_modifier is any of
|
Follows the rules of Class Fields and Method Definition |
Returning from a method |
return expression; return; |
Same as Java, but can ommit the return statement - in that case the last expression evaluated is returned. | Same as Java, but can ommit the return statement - in that case the last expression evaluated is returned. |
Null | null | null - Guillaume Laforge notes that "Null Object Pattern" is supported in Groovy. See also: NullObject. So, you can call null.toString() for example. |
null Looks like you can call methods on a null reference, the returned value will be default value the return Type accepts. class X { function doit() { 42 } } var x:X = null java.lang.System.out.println( x.doit() ) // doesn't throw an NPE // prints 0 |
Arrays |
int[] a = new int[10]; a[0] = 3; |
int[] a = new int[10] a[0] = 3 |
Not supported JavaFx has Sequences (chapter 6), they are not Arrays nor objects. They do not support nesting, in other words the following are equivalent var s1 = [1,2,3,4,5]; var s2 = [1,2,[3,4,[5]]]; |
Array Literals |
int[] a = {0,1,2}; a[0] = 3; |
int[] a = [0,1,2] a[0] = 3 |
var s1 = [1,2,3,4,5]; |
Lists | Supported by the Collections framefork (JSL), not really part of the language |
List list = [0,1,2] list[0] = 'Foo' list[10] = 11 Lists can be heterogeneous Lists grow as needed |
Same as in Java |
Hash Literals | Not supported. (See java.util.Map) |
def hash = [key:'value', 'id': 1] hash.key = 'value2' // bean like access hash[key] = 'value3' // hash like access |
Same as in Java |
Object Initialization |
class Person { [access_modifier] Person( [args] ) { // initialize } } |
class Person { [access_modifier] Person( [args] ) { // initialize } } |
Does not support constructors, but has object literals class Foo { attribute bar:Number; } var foo = Foo { bar: 1 } You may define a function that initializes the object with an object literal |
Reference to current object | this | this | this |
Varargs |
class Person { public void greet(Object...args) {   // access the "args" array here } } note: works on JDK5+ |
class Person { public void greet(Object...args) {   // access the "args" array here } } note: works on JDK5+ class Person { public void greet(Object[]args) {   // access the "args" array here } } note: any array type will do only if it is the last parameter defined. Works on JDK4+ |
Not supported |
Extending another class |
class Employee extends Person { } |
class Employee extends Person { } |
class Employee extends Person { } note: supports multiple inheritance if the class is not plain (chapter 2) |
Referring to super class method | super.foo(); | super.foo() | super.foo(); |
Inner, neste and anonymous classes |
// Inner class class Book { class Order { } } // Nested class class Node { static class AndNode { } static class OrNode { } } // Anonymous class class Main { public Runnable getRunnable() { return new Runnable() { public void run() { // code } }; } } |
Not Supported. Annonymous inner classes may be supported in a future version. Closures may be used in most cases instead. |
Not Supported. |
Closures |
Not Supported. May be supported in a future version of Java (JDK7+) |
{ param1, param2 -> /* statements */ } /* single param named as "it" */ { /* statements */ } Examples: [3, 4, 4].each { x -> println(x) } [3, 4, 4].each { println(it); } For detailed explanation, refer to Closures in Groovy |
Not Supported. JavaFx has functions that in some cases behave like Groovy's closures (chapter 3, chapter 8) |
Exception Handling |
try { // statements } catch(Exception e) { // statements } finally { // statements } |
Same as in Java except that declarations of exceptions in method signature are optional - even for checked exceptions. | Same as in Java. |
Modules, Namespaces |
package com.acme.foo; import java.net.*; |
Same as in Java. | Same as in Java. |
Specialized features of Groovy/JavaFx Script will be covered in future posts.