Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

The Groovy Programming Language runs on top of the Java Runtime Environment, which itself runs on almost any computer system, such as Windows, Linux, and Macintosh. If you don't have Groovy installed, see these pages:
    Installing Groovy
    Running Groovy
If you don't have the Java Runtime Environment:
    Installing Java

These tutorials for those new to both Java and Groovy are in a sequence that builds on knowledge already presented. This tutorial therefore starts with the basics. Throughout, we use code examples rather than lengthy explanations to present the features of Groovy, so you might miss things if you just skim. We don't (yet) explain what you would use the features for, but rely on your previous programming background for this.

The code snippets in these tutorials use comments to explain things:

Code Block
//comment like this to end of line, ignoring */ and /* and ' and "
/*or comment like this, ignoring // and ' and " until: */
/*or comment over 
many lines, /*with no nesting*/

Groovy code can contain strings:

Code Block
'A string can be within single quotes on one line...'
'''...or within triple single quotes
over many lines, ignoring // and */ and /* comment delimiters,...'''
"...or within double quotes..."
"""...or within triple double quotes
over many lines."""

Each line here does the same:

Code Block
println 'hello, world' //the function 'println' prints a string then newline
print 'hello, world\n' //'print' doesn't print newline, but we can embed
                       //newlines ('\n' on Unix/Linux, '\r\n' on Windows)
println 'hello' + ', ' + 'world' // + joins strings together
print 'hello, '; println 'world'
                       //use semi-colons to join two statements on one line
println( 'hello, world' )
             //can put command parameter in parens, sometimes we might have to
def a= 'world'; println 'hello, ' + a
                       //'def' to define a variable and give it a value
print 'hello, world'; println()
  //empty parens must be used for no-arg functions; here, prints a blank line
def b= 'hello', c= 'world'; println "$b, ${c}"
                       //$ in print string captures variable's value

We can also assign integers and decimals to variables:

Code Block
def g = 7, groovy = 10.2
  //we can separate more than one defined variable by a comma
print g + ', ' + groovy + '\n' //prints: 7, 10.2
assert g + ', ' + groovy == '7, 10.2' //we can use assert statement and == 
                                      //operator to understand examples

We can use operators like + - * / and parentheses ( ) with numbers, following usual math grouping rules:

Code Block
assert 4 * ( 2 + 3 ) - 6 == 14 //integers only
assert 2.5 + 7 == 9.5
assert 7 / 4 == 1.75 //decimal number or division converts expression to decimal

We can use the operators == > < >= <= != with numbers, the values true and false, the operators ! (not), && (and), and || (or), all with parentheses, to produce boolean expressions:

Code Block
assert 2 > 3 == false
assert 7 <= 9
assert 7 != 2
assert true
assert ! false
assert 2 > 3 || 7 <= 9
assert ( 2 > 3 || 4 < 5 ) && 6 != 7

Variables are versatile:

Code Block
def a
assert a == null
  //variables defined but not given a value have special value null
def b = 1
assert b == 1
b = 2
assert b == 2 //variables can be re-assigned to
b = 'cat'
assert b == 'cat' //they can be re-assigned different types/classes of data
b = null
assert b == null //they can be unassigned

All names in Groovy, including variable names, can contain any alphabetic character or the underscore, and contain any digit not in first position:

Code Block
def abc= 4
def a23c= 4
def ab_c= 4
def _abc= 4

def ABC= 4
assert abc == ABC //although their values are the same...
assert ! abc.is( ABC ) //...the variables 'abc' and 'ABC' are different,
                       //the names being case-sensitive

/*these each produce compile errors when uncommented...
def abc //already defined
def a%c= 4 //not a valid name because it contains a symbol other than _
def 2bc= 4 //may not contain a digit in first position
*/

All data in Groovy is built from "classes" and instances of them. Class names by convention begin with an uppercase character:

Code Block
assert Byte.MAX_VALUE == 127
  //a class can have attached variables, called 'fields'
assert Byte.parseByte('34') == 34
  //a class can have attached functions, called 'methods'
def b= new Byte('34')
  //we can create an 'instance' of a class using the 'new' keyword
assert b.intValue() == 34
  //each instance can also have attached fields and methods

We can inspect the class of any entity, such as numbers and strings, using the class field:

Code Block
assert 4.class == Integer //the common types have both a short name...
assert 4.class == java.lang.Integer //...and a long name
assert 4.5.class == BigDecimal
assert 'hello, world'.class == String
def a= 7
assert a.class == Integer

There are many predefined classes in Groovy, but only the most common ones are always visible to Groovy code. Most need to be qualified with a "package" name, eg, 'java.text.DecimalFormat', or the package must be imported beforehand:

Code Block
import java.text.*
assert new DecimalFormat( '#,#00.0#' ).format( 5.6789 ) == '05.68'

Or:

Code Block
assert new java.text.DecimalFormat( '#,#00.0#' ).format( 5.6789 ) == '05.68'

If a line can be interpreted as a valid statement, it will be:

Code Block
def i=
1 //because 'def i=' isn't a valid statement,
  //the '1' is appended to the previous line

//a compile error when uncommented: 'def j' is valid, so is interpreted as
//a statement. Then the invalid '= 1' causes the error...
/*
def j
= 1
*/

def k \
= 1 //a backslash ensures a line is never interpreted as a standalone statement

Sometimes code in a script doesn't compile: we comment it out in our examples. Other code compiles but generates a "checked exception" which we can catch and handle:

Code Block
try{
  'moo'.toLong() //this will generate an exception
  assert false 
      //this code should never be reached, so will always fail if executed
}catch(e){ assert e instanceof NumberFormatException }
  //we can check the exception type using 'instanceof'

We can use square brackets [ ] to represent both ordered lists and key mappings:

Code Block
def list= [1, 2, 3]
list= [] //empty list
list= [1, 'b', false, 4.5 ] //mixed types of values OK
assert list[0] == 1 && list[1] == 'b' && ! list[2] && list[3] == 4.5
  //we can refer to items individually by index

def map= [1:'a', 2:'b', 3:'c'] //map indicated with colon :
map= [:] //empty map
map= ['a': 1, 'b': 'c', 'groovy': 78.9, 12: true] //mixed types of values
assert map['a'] == 1 && map['b'] == 'c' && map['groovy'] == 78.9 && map[12]
  //we can refer to values individually by key

'each' tells the code following it to execute for each item in a list or map:
//for every item in list, assign to 'it' and execute the following code...
[ 2, -17, +987, 0 ].each{
  println it
}
//we can specify a different name for the argument other than the default...
[ 2, -17, +987, 0 ].each{ n -> 
  println n
}
//we can specify two or more arguments, as with this map...
[ 1: 3, 2: 6, 3: 9, 4: 12 ].each{ k, v-> 
  assert k * 3 == v
}

We can specify a list as a 'range', ie, by only the first and last items:

Code Block
( 3..7 ).each{ println it } //prints numbers 3, 4, 5, 6, and 7
( 3..<7 ).each{ println it } //prints numbers 3, 4, 5, and 6 //excludes 7

We can convert data of one type to another using the 'as' keyword:

Code Block
assert ('100' as Integer) == 100

Sometimes, we need to use a more efficient type of list known as an array, where the type of each element must be the same. Arrays can't be represented directly in the syntax, but we can convert a list to one easily:

Code Block
def x= ['a', 'b', 'c'] as Integer[] //convert each item in list to an Integer
assert x[0] == 97 && x[1] == 98 && x[2] == 99 //access each element individually

We can choose between two execution options using the if-else-statement:

Code Block
def a= 2
if( a < 5 ){
  println "a, being $a, is less than 5."
}else{
  assert false //this line should never execute
}

We can execute some code a certain number of times:

Code Block
def i=0
10.times{ println i++ } //increment i by 1 after printing it

//another less declarative style of looping...
while( i > 0 ){
  println i-- //decrement i by after printing it
}

We can enclose code in parentheses and execute it later. The enclosed code is called a "closable block" or "closure":

Code Block
def c= { def a= 5, b= 9; a * b }
assert c() == 45

[ { def a= 'ab'; a + 'bc' },
  { 'abbc' },
].each{ assert it() == 'abbc' }

We can spawn new threads from our main thread:

Code Block
def i=0, j=0
def f= new File('TheOutput.txt') //create or overwrite this file
Thread.start{
  while(true){
    i++
    if(i%1000 == 0) f<< 'S' //spawned thread
  }
}
while(true){
  j++
  if(j%1000 == 0) f<< 'M' //main thread
}

After, say, 5 seconds, abort the program then look at the file. On many computers, it'll show a roughly equal distribution of 'S' and 'M', but there'll be some irregularities showing that thread scheduling isn't perfectly timed.

The tutorials following are grouped into functional areas, beginning with numeric processing, and build up to the advanced features of Groovy.