Java, Groovy & JavaFx: side to side 1 - No Fluff Just Stuff

Java, Groovy & JavaFx: side to side 1

Posted by: Andres Almiray on August 14, 2008

While experimenting with JavaFx Script I encountered a few gotchas switching from Java/Groovy, mostly related to my preconceptions of the language itself. Even though it is JVM language built with Java, being an specialized language for declarative UI building doesn't mean it will follow Java's steps all the way, nor other modern features brought into the JVM by Groovy. The following table summarizes many of the orthogonal features of the three languages, it is not a complete reference for any of them. The "official draft" of the JavaFX™ Script Programming Language Reference was used to learn more about the it. Disclaimer: I know Groovy better than JavaFx Script, if someone spots a mistake please let me know :-)

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
  • false
  • null references
  • empty Map
  • empty List
  • Matcher with no matches
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
  • public
  • protected
  • private
  • empty - means package protected [default access]
[access_modifier] Type name

where access_modifier is any of
  • public [default access]
  • protected
  • private
If no access modifier is provided then the field would be promoted to a property. Properties have their get/set methods autogenerated in bytecode which means that the following Groovy class

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
  • empty - [default access] ?
  • public
  • protected
  • private

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
  • public
  • protected
  • private
  • empty - means package protected [default access]
[access_modifier] static Type name

where access_modifier is any of
  • public
  • protected
  • private
[access_modifier] static attribute name [:Type]

where access_modifier is any of
  • empty - [default access] ?
  • public
  • protected
  • private
note: Type may be optional due to type inference.
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
  • public
  • protected
  • private
  • empty - means package protected [default access]
class Person {
  [access_modifier] Type name() {
    // statements
  }
}

where access_modifier is any of
  • public
  • protected
  • private
  • empty - same as public [default access]
class Person {
  [access_modifier] function name() [:Type] = {
    // expressions
  }
}

where access_modifier is any of
  • public
  • protected
  • private
  • empty - same as public [default access]
The type of the function may be optional
Static Method Definition class Person {
  [access_modifier] static Type name() {
    // statements
  }
}

where access_modifier is any of
  • public
  • protected
  • private
  • empty - same as public [default access]
class Person {
  [access_modifier] static function name() [:Type]{
    // statements
  }
}

where access_modifier is any of
  • public
  • protected
  • private
  • empty - same as public [default access]
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.
Andres Almiray

About Andres Almiray

Andres is a Java/Groovy developer and a Java Champion with more than 20 years of experience in software design and development. He has been involved in web and desktop application development since the early days of Java. Andres is a true believer in open source and has participated on popular projects like Groovy, Griffon, and DbUnit, as well as starting his own projects (Json-lib, EZMorph, GraphicsBuilder, JideBuilder). Founding member of the Griffon framework and Hackergarten community event. https://ch.linkedin.com/in/aalmiray

Why Attend the NFJS Tour?

  • » Cutting-Edge Technologies
  • » Agile Practices
  • » Peer Exchange

Current Topics:

  • Languages on the JVM: Scala, Groovy, Clojure
  • Enterprise Java
  • Core Java, Java 8
  • Agility
  • Testing: Geb, Spock, Easyb
  • REST
  • NoSQL: MongoDB, Cassandra
  • Hadoop
  • Spring 4
  • Cloud
  • Automation Tools: Gradle, Git, Jenkins, Sonar
  • HTML5, CSS3, AngularJS, jQuery, Usability
  • Mobile Apps - iPhone and Android
  • More...
Learn More »