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 Java developer embarking on a Groovy adventure will always have Java in mind, and will progressively learn Groovy, one feature at a time, becoming more productive and writing more idiomatic Groovy code. This document's purpose is to guide such a developer along the way, teaching some common Groovy syntax style, new operators, and new features like closures, etc. This guide is not complete and only serves as a quick intro and a base for further guideline sections should you feel like contributing to the document and enhancing it.</p><h3>No semicolons</h3><p>When coming from a C / C++ / C# / Java background, we're so used to semicolons, that we put them everywhere. Even worse, Groovy supports 99% of Java's syntax, and sometimes, it's so easy to paste some Java code into your Groovy programs, that you end up with tons of semicolons everywhere. But... semicolons are optional in Groovy, you can omit them, and it's more idiomatic to remove them.</p><h3>Return keyword optional</h3><p>In Groovy, the last expression evaluated in the body of a method can be returned without necessiting the 'return' keyword. specially for short methods and for closures, it's nicer to omit it for brevity:</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>String toString() { return "a server" } String toString() { "a server" } </pre></td></tr></table><p>But sometimes, this doesn't look to good when you're using a variable, and see it visually twice on two rows:</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 props() { def m1 = [a: 1, b: 2] m2 = m1.findAll { k, v -> v % 2 == 0 } m2.c = 3 m2 } </pre></td></tr></table><p>In such case, either putting a newline before the last expression, or explicitely using 'return' may yield better readability.</p><p>I, for myself, sometimes use the return keyword, sometimes not, it's often a matter of taste. But often, inside of closure, we omit it more often than not, for example. So even if the keyword is optional, this is by no means mandatory to not use it if you think it halters the readability of your code.</p><p>A word of caution, however. When using methods which are defined with the 'def' keyword instead of a specific concrete type, you may be surprise to see the last expression being returned sometimes. So usually prefer using a specific return type like void or a type. In our example above, imagine we forgot to put m2 as last statement to be returned, the last expression would be m2.c = 3, which would return... 3, and not the map you expect.</p><p>Statements like if/else, try/catch can thus return a value as well, as there's a "last expression" evaluated in those 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 foo(n) { if(n == 1) { "Roshan" } else { "Dawrani" } } assert foo(1) == "Roshan" assert foo(2) == "Dawrani" </pre></td></tr></table><h3>Def and type</h3><p>As we're talking about def and types, I often see developers using both 'def' and a type. But 'def' is redundant here. So make a choice, either use 'def' or a type.</p><p>So don't write:</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 String name = "Guillaume" </pre></td></tr></table><p>But:</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>String name = "Guillaume" </pre></td></tr></table><p>When using def in Groovy, the actual type holder is Object (so you can assign any object to variables defined with def, and return any kind of object if a method is declared returning def).</p><p>When defining a method with untyped parameters, you can use 'def' but it's not needed, so we tend to omit them. So instead of:</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>void doSomething(def param1, def param2) { }</pre></td></tr></table><p>Prefer:</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>void doSomething(param1, param2) { }</pre></td></tr></table><p>But as we mention in the last section of the document, it's usually better to type your method parameters, so as to help with documenting your code, and also help IDEs for code-completion, or for leveraging the static type checking or static compilation capabilities of Groovy.</p><p>Another place where 'def' is redundant and should be avoided is when defining constructors:</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 MyClass { def MyClass() {} }</pre></td></tr></table><p>Instead, just remove the 'def':</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 MyClass { MyClass() {} }</pre></td></tr></table><h3>Public by default</h3><p>By default, Groovy considers classes and methods 'public'. So you don't have to use the 'public' modifier everywhere something is public. Only if it's not public, you should put a visibility modifier.</p><p>So instead of:</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>public class Server { public String toString() { return "a server" } } </pre></td></tr></table><p>Prefer the more concise:</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 Server { String toString() { "a server" } } </pre></td></tr></table><p>You may wonder about the 'package-scope' visibility, and the fact Groovy allows one to omit 'public' means that this scope is not supported by default, but there's actually a special Groovy annotation which allows you to use that visibility:</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 Server { @PackageScope Cluster cluster } </pre></td></tr></table><h3>Omitting parentheses</h3><p>Groovy allows you to omit the parentheses for top-level expressions, like with the println command:</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>println "Hello" method a, b </pre></td></tr></table><p>vs:</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>println("Hello") method(a, b) </pre></td></tr></table><p>When a closure is the last parameter of a method call, like when using Groovy's 'each‘ iteration mechanism, you can put the closure outside the closing parens, and even omit the parentheses:</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>list.each( { println it } ) list.each(){ println it } list.each { println it } </pre></td></tr></table><p>Always prefer the third form, which is more natural, as an empty pair of parentheses is just useless syntactical noise!</p><p>There are some cases where Groovy doesn't allow you to remove parentheses. As I said, top-level expressions can omit them, but for nested method calls or on the right-hand side of an assignment, you can't omit them there.</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 foo(n) { n } println foo 1 // won't work def m = foo 1 </pre></td></tr></table><h3>Classes as first-class citizens</h3><p>The .class suffix is not needed in Groovy, a bit like in Java's instanceof.</p><p>For example:</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>connection.doPost(BASE_URI + "/modify.hqu", params, ResourcesResponse.class) </pre></td></tr></table><p>Using GStrings we're going to cover below, and using first class citizens:</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>connection.doPost("${BASE_URI}/modify.hqu", params, ResourcesResponse) </pre></td></tr></table><h3>Getters and Setters</h3><p>In Groovy, a getters and setters form what we call a "property", and offers a shortcut notation for accessing and setting such properties. So instead of the Java-way of calling getters / setters, you can use a field-like access notation:</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>resourceGroup.getResourcePrototype().getName() == SERVER_TYPE_NAME resourceGroup.resourcePrototype.name == SERVER_TYPE_NAME resourcePrototype.setName("something") resourcePrototype.name = "something" </pre></td></tr></table><p>When writing your beans in Groovy, often called POGOs (Plain Old Groovy Objects), you don't have to create the field and getter / setter yourself, but let the Groovy compiler do it for you.</p><p>So instead of:</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 Person { private String name String getName() { return name } void setName(String name) { this.name = name } } </pre></td></tr></table><p>You can simply write:</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 Person { String name } </pre></td></tr></table><p>As you can see, a free standing 'field' without modifier visibility actually makes the Groovy compiler to generate a private field and a getter and setter for you.</p><p>When using such POGOs from Java, the getter and setter are indeed there, and can be used as usual, of course.</p><p>Although the compiler creates the usual getter/setter logic, if you wish to do anything additional or different in those getters/setters, you're free to still provide them, and the compiler will use your logic, instead of the default generated one.</p><h3>Initializing beans with named parameters and the default constructor</h3><p>With a bean like:</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 Server { String name Cluster cluster } </pre></td></tr></table><p>Instead of setting each setter in subsequent statements as follows:</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 server = new Server() server.name = "Obelix" server.cluster = aCluster </pre></td></tr></table><p>You can use named parameters with the default constructor (first the constructor is called, then the setters are called in turn):</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 server = new Server(name: "Obelix", cluster: aCluster) </pre></td></tr></table><h3>Using with() for repeated operations on the same bean</h3><p>Named-parameters with the default constructor is interesting when creating new instances, but what if you are updating an instance that was given to you, do you have to repeat the 'server' prefix again and again? No, thanks to the with() method that Groovy adds on all objects of any kind:</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>server.name = application.name server.status = status server.sessionCount = 3 server.start() server.stop() </pre></td></tr></table><p>vs:</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>server.with { name = application.name status = status sessionCount = 3 start() stop() } </pre></td></tr></table><h3>Equals and ==</h3><p>Java's == is actually Groovy's is() method, and Groovy's == is a clever equals()!<br /> To compare the references of objects, instead of ==, you should use a.is(b).<br /> But to do the usual equals() comparison, you should prefer Groovy's ==, as it also takes care of avoiding NullPointerException, independently of whether the left or right is null or not.</p><p>Instead of:</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>status != null && status.equals(ControlConstants.STATUS_COMPLETED) </pre></td></tr></table><p>Do:</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>status == ControlConstants.STATUS_COMPLETED </pre></td></tr></table><h3>GStrings (interpolation, multiline)</h3><p>We often use string and variable concatenation in Java, with many opening / closing of double quotes, plus signs, and \n characters for newlines. With interpolated strings (called GStrings), such strings look better and are less painful to type:</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>throw new Exception("Unable to convert resource: " + resource) </pre></td></tr></table><p>vs:</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>throw new Exception("Unable to convert resource: ${resource}") </pre></td></tr></table><p>Inside the curly braces, you can put any kind of expression, not just variables. For simple variables, or variable.property, you can even drop the curly braces:</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>throw new Exception("Unable to convert resource: $resource") </pre></td></tr></table><p>You can even lazily evaluate those expressions using a closure notation with ${-> resource }. When the GString will be coerced to a String, it'll evaluate the closure and get the toString() representation of the return value. Example:</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 i = 3 def s1 = "i's value is: ${i}" def s2 = "i's value is: ${-> i}" i++ assert s1 == "i's value is: 3" // eagerly evaluated, takes the value on creation assert s2 == "i's value is: 4" // lazily evaluated, takes the new value into account </pre></td></tr></table><p>When strings and their concatenated expression are long in Java:</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>throw new PluginException("Failed to execute command list-applications:" + " The group with name " + parameterMap.groupname[0] + " is not compatible group of type " + SERVER_TYPE_NAME) </pre></td></tr></table><p>You can use the \ continuation character (this is not a multiline string):</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>throw new PluginException("Failed to execute command list-applications: \ The group with name ${parameterMap.groupname[0]} \ is not compatible group of type ${SERVER_TYPE_NAME}") </pre></td></tr></table><p>Or using multiline strings with triple quotes:</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>throw new PluginException("""Failed to execute command list-applications: The group with name ${parameterMap.groupname[0]} is not compatible group of type ${SERVER_TYPE_NAME)}""") </pre></td></tr></table><p>You can also strip the indentation appearing on the left side of the multiline strings by calling .stripIndent() on that string.</p><p>Also note the difference between single quotes and double quotes in Groovy: single quotes always create Java Strings, without interpolation of variables, whereas double quotes either create Java Strings or GStrings when interpolated variables are present.</p><p>For multiline strings, you can triple the quotes: ie. triple double quotes for GStrings and triple single quotes for mere Strings.</p><p>If you need to write regular expression patterns, you should use the "slashy" string notation:</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>assert "foooo/baaaaar" ==~ /fo+\/ba+r/</pre></td></tr></table><p>The advantage of the "slashy" notation is that you don't need to double escape backslashes, making working with regex a bit simpler.</p><p>Last but not least, prefer using single quoted strings when you need string constants, and use double quoted strings when you are explicitly relying on string interpolation.</p><h3>Native syntax for data structures</h3><p>Groovy provides native syntax constructs for data structures like lists, maps, regex, or ranges of values. Make sure to leverage them in your Groovy programs.</p><p>Here are some examples of those native constructs:</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 = [1, 4, 6, 9] // by default, keys are Strings, no need to quote them // you can wrap keys with () like [(variableStateAcronym): stateName] to insert a variable or object as a key. def map = [CA: 'California', MI: 'Michigan'] def range = 10..20 def pattern = ~/fo*/ // equivalent to add() list << 5 // call contains() assert 4 in list assert 5 in list assert 15 in range // subscript notation assert list[1] == 4 // add a new key value pair map << [WA: 'Washington'] // subscript notation assert map['CA'] == 'California' // property notation assert map.WA == 'Washington' // matches() strings against patterns assert 'foo' =~ pattern </pre></td></tr></table><h3>The Groovy Development Kit</h3><p>Continuing on the data structures, when you need to iterate over collections, Groovy provides various additional methods, decorating Java's core data structures, like each{}, find{}, findAll{}, every{}, collect{}, inject{}. These methods add a functional flavor to the programming language and help working with complex algorithms more easily. Lots of new methods are applied to various types, through decoration, thanks to the dynamic nature of the language. You can find lots of very useful methods on String, Files, Streams, Collections, and much more:</p><p><a href="http://groovy.codehaus.org/groovy-jdk/">http://groovy.codehaus.org/groovy-jdk/</a></p><h3>The power of switch</h3><p>Groovy's switch is much more powerful than in C-ish languages which usually only accept primitives and assimilated. Groovy's switch accepts pretty much any kind of type.</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 = 1.23 def result = "" switch (x) { case "foo": result = "found foo" // lets fall through case "bar": result += "bar" case [4, 5, 6, 'inList']: result = "list" break case 12..30: result = "range" break case Integer: result = "integer" break case Number: result = "number" break default: result = "default" } assert result == "number" </pre></td></tr></table><p>And more generally, types with an isCase() method can also decide whether a value corresponds with a case</p><h3>Import aliasing</h3><p>In Java, when using two classes of the same name but from different packages, like java.util.List and java.awt.List, you can import one class, but have to use a fully-qualified name for the other.</p><p>Also sometimes, in your code, when using often a long class name, and the code becomes a bit more verbose.</p><p>To improve such situations, Groovy features import aliasing:</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>import java.util.List as juList import java.awt.List as aList import java.awt.WindowConstants as WC </pre></td></tr></table><p>You can also import methods statically:</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>import static pkg.SomeClass.foo foo() </pre></td></tr></table><h3>Groovy Truth</h3><p>All objects can be 'coerced' to a boolean value: everything that's null, void or empty evaluates to false, and if not, evaluates to true.<br /> So instead of writing if (name != null && name.length > 0) {}, you can just do if (name) {}. Same thing for collections, etc.<br /> Thus, you can use some shorcuts in things like while(), if(), the ternary operator, the Elvis operator (see below), etc.</p><p>It's even possible to customize the Groovy Truth, by adding an boolean asBoolean() method to your classes!</p><h3>Safe graph navigation</h3><p>Groovy supports a variant of the . operator to safely navigate an object graph.<br /> In Java, when you're interested in a node deep in the graph and need to check for null, you often end up writing complex if, or nested if statements like this:</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>if (order != null) { if (order.getCustomer() != null) { if (order.getCustomer().getAddress() != null) { System.out.println(order.getCustomer().getAddress()); } } } </pre></td></tr></table><p>With ?. safe dereference operator, you can simplify such code with:</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>println order?.customer?.address </pre></td></tr></table><p>Nulls are checked throughout the call chain and no NullPointerException will be thrown if any element is null, and the resulting value will be null if something's null.</p><h3>Assert</h3><p>To check your parameters, your return values, and more, you can use the 'assert' statement.<br /> Contrary to Java's assert, asserts don't need to be activated to be working, so asserts are always checked.</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 check(String name) { // name non-null and non-empty according to Groovy Truth assert name // safe navigation + Groovy Truth to check assert name?.size() > 3 } </pre></td></tr></table><p>You'll also notice the nice output that Groovy's "Power Assert" statement provides, with a graph view of the various values of each sub-expressions being asserted.</p><h3>Elvis operator for default values</h3><p>The Elvis operator is a special ternary operator shortcut which is handy to use for default values.<br /> We often have to write code like:</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 result = name != null ? name : "Unknown" </pre></td></tr></table><p>Thanks to Groovy Truth, the null check can be simplified to just 'name'.<br /> And to go even further, since you return 'name' anyway, instead of repeating name twice in this ternary expression, we can somehow remove what's in between the question mark and colon, by using the Elvis operator, so that the above becomes:</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 result = name ?: "Unknown" </pre></td></tr></table><h3>Catch any exception</h3><p>If you don't really care of the exception which are thrown inside your try block, you can simply catch any of them and simply omit the type of the caught exception. So instead of catching the throwables like 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>try { // ... } catch (Throwable t) { // something bad happens } </pre></td></tr></table><p>Then catch anything ('any' or 'all', or whatever makes you think it's anything):</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>try { // ... } catch (any) { // something bad happens } </pre></td></tr></table><h3>Optional typing advice</h3><p>I'll finish on some words on when and how to use optional typing. Groovy lets you decide whether you use explicit strong typing, or when you use 'def'.</p><p>I've got a rather simple rule of thumb: whenever the code you're writing is going to be used by others as a public API, you should always favor the use of strong typing, it helps making the contract stronger, avoids possible passed arguments type mistakes, gives better documentation, and also helps the IDE with code completion whenever the code is for your use only, like private methods, or when the IDE can easily infer the type, then you're more free to decide when to type or not</p>
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