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:
//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:
'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:
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:
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:
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:
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:
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:
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:
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:
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:
import java.text.* assert new DecimalFormat( '#,#00.0#' ).format( 5.6789 ) == '05.68'
Or:
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:
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:
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:
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:
( 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:
assert ('a' as Integer) == 97 //Unicode (and ASCII) representation of character 'a'
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:
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:
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:
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":
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:
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.






