Skip to content
Skip to breadcrumbs
Skip to header menu
Skip to action menu
Skip to quick search
Quick Search
Browse
Pages
Blog
Labels
Attachments
Mail
Advanced
What’s New
Space Directory
Feed Builder
Keyboard Shortcuts
Confluence Gadgets
Log In
Sign Up
Dashboard
Groovy
Copy Page
You are not logged in. Any changes you make will be marked as
anonymous
. You may want to
Log In
if you already have an account. You can also
Sign Up
for a new account.
This page is being edited by
.
Paragraph
Paragraph
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Preformatted
Quote
Bold
Italic
Underline
More colours
Strikethrough
Subscript
Superscript
Monospace
Clear Formatting
Bullet list
Numbered list
Outdent
Indent
Align left
Align center
Align right
Link
Table
Insert
Insert Content
Image
Link
Attachment
Symbol
Emoticon
Wiki Markup
Horizontal rule
tinymce.confluence.insert_menu.macro_desc
Info
JIRA Issue
Status
Gallery
Tasklist
Table of Contents
Other Macros
Page Layout
No Layout
Two column (simple)
Two column (simple, left sidebar)
Two column (simple, right sidebar)
Three column (simple)
Two column
Two column (left sidebar)
Two column (right sidebar)
Three column
Three column (left and right sidebars)
Undo
Redo
Find/Replace
Keyboard Shortcuts Help
<p>A Groovy script is a sequence of statements:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def a= 1 assert "a is $a" == 'a is 1' def b= 2; assert "b is $b" == 'b is 2' //if two statements on one line, separate by semicolons def c= 3; ; def d= 4 //empty statement in between </pre></td></tr></table> <p>When defining classes, we can provide 'asType' methods to convert the class into another using the 'as' operator. Classes we've seen in previous tutorials that convert to another using 'as' (eg, Integer, BigDecimal, String) use the 'asType' method under the hood:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> class A{ def x Object asType(Class c){ if(c == B) return new B(x:x*3) } } class B{ def x } def a= new A(x:3) def b1= a.asType(B) assert b1.class == B && b1.x == 9 def b2= a as B //more common, shortcut syntax for asType() assert b2.class == B && b2.x == 9 </pre></td></tr></table> <p>We can use 'as' to convert a list into a class instance using the list elements as constructor arguments:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> class A{ int x,y A(x,y){ this.x=x; this.y=y } String toString(){ "x: $x; y: $y" } } def a= [1,2] as A assert a.class == A && a.toString() == 'x: 1; y: 2' </pre></td></tr></table> <h3>Conditional Statements</h3> <p>The if and if-else statements let us choose subsequent statements to execute based on a condition:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def x= 7 if( x > 4 ){ println 'x is greater than 4' } //if-statement (no 'else' clause) if( x > 4 ) println 'x is greater than 4' //curlies optional if only one statement //if-else statement... if( x > 4 ){ println 'x is greater than 4' }else{ println 'x is less than or equal to 4' } if( x > 8 ) println 'x is greater than 8' //again, curlies optional if only one statement else println 'x is less than or equal to 8' //an 'else' clause always belongs to def result if( x > 4 ) if( x > 8 ) result= 'x is greater than 8' else result= 'x is less than or equal to 8' //a single 'else' with two 'if' clauses belongs to the innermost assert result == 'x is less than or equal to 8' </pre></td></tr></table> <p>The meaning of the 'in' operator depends whether its context in the code is conditional or iterative. When in a conditional context, the 'isCase' method of the target is invoked:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> class A{ boolean isCase(Object o){ if(o == 'A') return true else return false } } def a= new A() assert a.isCase('A') assert 'A' in a //more common, shortcut syntax for isCase() assert ! (a.isCase('Z')) assert ! ('Z' in a) //more common, shortcut syntax for isCase() </pre></td></tr></table> <p>The switch statement inspects an expression and resumes execution from the first matching case-expression, ie, regex matched, list or set or range contained in, class an instance of, or object equal to:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def values= [ 'abc': 'abc', 'xyz': 'list', 18: 'range', 31: BigInteger, 'dream': 'something beginning with dr', 1.23: 'none', ] values.each{ def result switch( it.key ){ case 'abc': //if switched expression matches case-expression, execute all //statements until 'break' result= 'abc' break case [4, 5, 6, 'xyz']: result= 'list' break case 'xyz': //this case is never chosen because 'xyz' is matched by //previous case, then 'break' executed result= 'xyz' break case 12..30: result= 'range' break case Integer: result= Integer //because this case doesn't have a 'break', result //overwritten by BigInteger in next line case BigInteger: result= BigInteger break case ~/dr.*/: result= 'something beginning with dr' break case {it instanceof Integer && it>30}: //use Closure result= 'result is > 30' break default: result= 'none' } assert result == it.value } </pre></td></tr></table> <p>When we supply our own values in the case-expression, the 'isCase' method is invoked to determine whether or not the switch-expression is matched. If there's no 'isCase' method, the 'equals' method is used to test for equality:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> class A{ boolean isCase(Object switchValue){ //'isCase' method used for case-expression if(switchValue == 'Hi') return true else return false } } switch( 'Hi' ){ case new A(): assert true break default: assert false } class B{ boolean equals(Object switchValue){ //'equals' method used for case-expression this.class == switchValue.getClass() } } switch( new B() ){ case new B(): assert true break default: assert false } </pre></td></tr></table> <h3>Iterative Statements</h3> <p>The while statement lets us iterate through a block of code:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def x= 0, y= 0 while( x < 5 ){ x++ y += x } assert x == 5 && y == 15 while( x < 10 ) x++ //curlies optional if only one statement assert x == 10 while( x < 15 ){ //we can break out of a while-loop using 'break' x++ if( x == 12 ) break } assert x == 12 while( x != 15 && x != 18 ){ //we can jump to the next iteration of a while-loop using 'continue' x++ if( x == 15 ){ x++ continue } } assert x == 18 </pre></td></tr></table> <p>We've already seen the 'each' and other related method calls, which emulate the while-statement at a higher level of abstraction, but with some restrictions: the loop variable isn't available outside the loop, no guarantees are made about the order of iteration through the collection, and the 'break', 'continue', and 'return' commands aren't available:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> int n=1 while( n <= 5 ){ def y= 0 (1..n).each{ //loop variable, here 'it', not available outside loop y += it //if( y > 8 ) break //a syntax error when uncommented: 'break' command not available here } assert y == (n+1)*(n/2.0) //another way to add the numbers 1 to n n++ } </pre></td></tr></table> <p>Other method calls that loop are 'times', 'upto', 'downto', and 'step'. Like 'each', they don't allow 'break', 'continue', and 'return' commands, but do make guarantees about the order of iteration:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def a= 2 3.times{ a= a*a } assert a == 256 def list= [] 1.upto(5){ list<< it } assert list == [1, 2, 3, 4, 5] list= [] 5.3.downto(2.1){ //'upto', 'downto', and 'step' also work with decimal numbers list<< it } assert list == [5.3, 4.3, 3.3, 2.3] list= [] 1.step(9.5, 2.5){ list<< it } assert list == [1, 3.5, 6, 8.5] </pre></td></tr></table> <p>We can label any statement with a name. Labelling a while loop lets any arbitrarily deep nested statement break out of or continue on from it:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> yonder: def d= 4 there: { def e= 5 here: if( e == 5 ){ def f= 6 there: def g= 7 //label can repeat a previously-used outer label } } there: def h= 8 //label can repeat a previously-used label at same syntactic level def i=0, j=0 outer: while( i<5 ){ //labelling a while loop is especially useful... j= 0 i++ while( j<5 ){ j++ if( i==3 && j==2 ) break outer //...because we can break out of a specified labelled while loop } } assert i==3 && j==2 def outer= 0, inner= 0 outer: while( outer != 5 && outer != 8 ){ //label can have same name as any variables inner= 0 outer++ while( inner<5 ){ inner++ if( outer==5 ){ outer++ continue outer //we can also continue on from a specified labelled while loop } } } assert outer==8 </pre></td></tr></table> <h3>For-Statements</h3> <p>For-statements are complex yet powerful iterative statements with many possible formats. When 'in' is used in the iterative context of a for-statement, the 'iterator' method of the target is invoked. The 'iterator' method must return an Iterator, defining at least the 'hasNext' and 'next' methods:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> class CountToFive{ def n= 0 def iterator(){ [ hasNext: { n<5 }, next: { n++ }, ] as Iterator } } def list= [] def counter= new CountToFive() for(int i in counter){ list<< i } assert list == [0, 1, 2, 3, 4] </pre></td></tr></table> <p>The for-statement works with many kinds of objects (eg, Collection, array, Map, String, regex, File, Reader, InputStream, etc):</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def list= [] for( e in [0, 1, 2, 3, 4] ){ //iterate over a list list<< e } assert list == [0, 1, 2, 3, 4] list= [] for( i in 1..9 ){ //iterate over a range list<< i } assert list == [1, 2, 3, 4, 5, 6, 7, 8, 9] list= [] for( e in (3..6).toArray() ){ //over an array list<< e } assert list == [3, 4, 5, 6] list= [] for( e in ['abc':1, 'def':2, 'xyz':3] ){ //over a map list<< e.value } assert list as Set == [1, 2, 3] as Set list= [] for( v in [1:'a', 2:'b', 3:'c'].values() ){ //over values in a map list<< v } assert list as Set == ['a', 'b', 'c'] as Set list = [] for( c in "abc" ){ //over the chars in a string list<< c } assert list == ['a', 'b', 'c'] </pre></td></tr></table> <p>We can use 'break' and 'continue' within a for-loop using 'in':</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def list = [] for( c in 'abc' ){ list<< c if( c == 'b' ) break } assert list == ['a', 'b'] list = [] for( c in 'abc' ){ if( c == 'b' ) continue list<< c } assert list == ['a', 'c'] </pre></td></tr></table> <p>'each' methods can also be considered as emulating for-loops at a higher level of abstraction, without the guarantees about the order of iteration, and the 'break', 'continue', and 'return' commands being unavailable:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def list= [] ['a', 'b', 'c'].each{ list<< it } assert list == ['a', 'b', 'c'] //instead of... list= [] for( item in ['a', 'b', 'c'] ){ list<< item } assert list == ['a', 'b', 'c'] </pre></td></tr></table> <p>Another format for the for-statement is the initializer-condition-incrementer format:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def list= [] for(def i=0; i<5; i++){ //first value an initializer, second a condition, third an incrementer list<< i } assert list == [0, 1, 2, 3, 4] //equivalent while-statement... list= [] try{ def i=0 //initializer while( i<5 ){ //condition list<< i i++ //incrementer } } assert list == [0, 1, 2, 3, 4] //for-statement with 'break' list= [] for(def i=0; i<5; i++){ list<< i if( i == 2 ) break } assert list == [0, 1, 2] //equivalent while-statement with 'break' list= [] try{ def i=0 while( i<5 ){ list<< i if( i == 2 ) break i++ } } assert list == [0, 1, 2] //for-statement with 'continue' list= [] for(def i=0; i<5; i++){ if( i == 2 ){ continue } list<< i } assert list == [0, 1, 3, 4] //equivalent while-statement with 'continue' list= [] try{ def i=0 while( i<5){ if( i == 2 ){ i++; continue } list<< i i++ } } assert list == [0, 1, 3, 4] </pre></td></tr></table> <p>We can have more than one initializer, and more than one incrementer:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> //two initializers and two incrementers... def list= [] for(def i=0; def j=10; i<5; i++; j++){ //the middle expression is the condition list<< i + j } assert list == [10, 12, 14, 16, 18] //three initializers and three incrementers... list= [] for(def i=0; def j=10; def k=20; i<3; i++; j++; k++){ list<< i + j + k } assert list == [30, 33, 36] //when there's an even number of expressions, the condition is just before //the middle... list= [] try{ def i=0 for(def j=10; i<5; i++; j++){ list<< i + j } } assert list == [10, 12, 14, 16, 18] //we can force in more initializers than incrementers by using //'null' statements... list= [] for(def i=0; def j=10; i<5; i++; null ){ list<< i + j } assert list == [10, 11, 12, 13, 14] </pre></td></tr></table> <h3>Operator Overloading</h3> <p>The precedence heirarchy of the operators, some of which we haven't looked at yet, is, from highest to lowest:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> $(scope escape) new ()(parentheses) [](subscripting) ()(method call) {}(closable block) [](list/map) . ?. *. (dots) ~ ! $ ()(cast type) **(power) ++(pre/post) --(pre/post) +(unary) -(unary) * / % +(binary) -(binary) << >> >>> .. ..< < <= > >= instanceof in as == != <=> & ^ | && || ?: = **= *= /= %= += -= <<= >>= >>>= &= ^= |= </pre></td></tr></table> <p>We've seen how the 'as' operator is mapped to the asType() method, and how the 'in' operator is mapped to the isCase() and iterator() methods. Many more operators have equivalent method names. We've seen how [] subscripting has equivalent methods getAt() and putAt() in the HashMap class. They are also equivalent when we define such methods on our own classes:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> class A{ int key def value def getAt(int n){ if(key == n) return value } void putAt(int n, def o){ key= n; value= o } } def a= new A() a[1]= 'abc' //calls putAt() assert a[1] == 'abc' //calls getAt() assert a[2] == null </pre></td></tr></table> <p>We've also seen how various operators have equivalent method names in the numerical classes, such as Integer, BigDecimal, float, etc. They, too, are also equivalent when we define such methods on our own classes:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> class OddNumber{ //only gives odd results to operations, adding 1 if necessary int value OddNumber(int n){ value= (n%2)? n: n+1 } def power(int n){ value**n } def multiply(int n){ def i= value*n; (i%2)? i: i+1 } def div(int n){ int i= value/n; (i%2)? i: i+1 } def mod(int n){ int i= value - div(n)*n; (i%2)? i: i+1 } def plus(int n){ int i= value + n; (i%2)? i: i+1 } def minus(int n){ int i= value - n; (i%2)? i: i+1 } def and(int n){ n == value } def or(int n){ n == value || (n == value-1) } def xor(int n) {n == value-1 } def leftShift(int n){ value= (n%2)? n: n+1 } def rightShift(int n){ (value * 10**n) + 1 } def rightShiftUnsigned(int n){ (value * 10**(n*2)) + 1 } def next(){ new OddNumber(value + 2) } def previous(){ new OddNumber(value - 2) } } def e= new OddNumber(6) assert e.value == 7 assert e**3 == 343 //calls power() assert e*4 == 29 //calls multiply() assert e/3 == 3 //calls div() assert e%3 == -1 //calls mod() assert e+5 == 13 //calls plus() assert e-1 == 7 //calls minus() assert e & 7 //calls and() assert e | 6 && e | 7 //calls or() assert e ^ 6 //calls xor() e<< 2 //calls leftShift() assert e.value == 3 assert e>>2 == 301 //calls rightShift() assert e>>>2 == 30001 //calls rightShiftUnsigned() assert (e++).value == 3 //calls next() assert e.value == 5 assert (++e).value == 7 assert e.value == 7 assert (e--).value == 7 //calls previous() assert e.value == 5 assert (--e).value == 3 assert e.value == 3 </pre></td></tr></table>
Please type the word appearing in the picture.
Attachments
Labels
Location
Watch this page
< Edit
Preview >
Loading…
Save
Cancel
Next hint
search
attachments
weblink
advanced