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
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>Groovy supports most of the signatures you know from Java. Since Groovy 1.5 Groovy supports full usage of generics in method declarations. Please see a Java tutorial for details.</p> <h2>General Form</h2> <p>I will often show a more general method signature like <code><strong>def foo(x, y, p1, p2, ..., pn)</strong></code><br /> This is not valid Groovy code, it is just there to show that a method named <code>foo</code> has <code>n+2</code> parameters. Usually this means also that <code>n</code> could be 0. In that case, the real resulting method signature would look like: <code><strong>def foo(x,y)</strong></code></p> <p>A form of <code><strong>def foo(x,y, p1, p2, ..., pn, q1, q2, ...., qm)</strong></code> would mean <code>n+m+2</code> parameters. Likewise a method call <code><strong>foo(x, p1, p2, ..., pn)</strong></code> is a method call with <code>n+1</code> arguments.</p> <p>I will use the word <strong>parameter</strong> when a method declaration is involved and <strong>argument</strong> in case of method calls. I will in general use the method name <code>foo</code> as a placeholder for a real method name. I will use <code>T</code> if a certain type is required. This could be Object, a primitive type or any class you like to use. If <code>T</code> cannot be chosen freely, then I will mention the possible types for <code>T</code></p> <h2>Variable Arguments</h2> <p>Like Java since Java5 Groovy supports variable arguments. To use them you have to give a special method signature where the last parameter is an array. <code><strong>def foo(p1, ...., pn, T... args)</strong></code>. Here foo supports <code>n</code> arguments by default, but also an unspecified number of further arguments exceeding <code>n</code>.</p> <p>Example:</p> <table class="wysiwyg-macro" data-macro-name="code" data-macro-default-parameter="java" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6amF2YX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>def foo(Object... args){args.length} assert foo() == 0 assert foo(1,2) == 2 </pre></td></tr></table> <p>In this example we defined a method <code>foo</code>, that is able to take any number of arguments, including no arguments at all. <code>args.length</code> will then specify the number of arguments. <code>T...</code> is the same syntax as used in Java and is internally represented as array where the parameter has a special flag set. Groovy allows as alternative <code>T[]</code>. That means any method that has an array as last parameter is seen by Groovy as a method that takes a variable number of arguments. These methods are seen as such by Java too, since the "variable arguments flag" is set. Methods defined in Java using <code>T...</code> behave like a variable arguments method. Methods defined in Java using <code>T[]</code> will not have the special flag set, but Groovy will still see them as variable arguments methods.</p> <p>If in case of <code>def foo(T[] args)</code>, <code>foo</code> is called with null, then <code>args</code> will be null and not an array of length 1 with null as only element. If <code>foo</code> is called with an array as argument, then <code>args</code> will be that array instead of an array of length 1 containing the given array as only element. <code>T...</code> will not behave different. This is no special logic we thought of, that is how variable arguments behave in Java too.</p> <p>One more important point to mention is maybe a method overloaded with a method that takes variable arguments. Groovy (and java) will select the most specific method, that means if there is a method taking one argument and the parameter type is an array and there is also another method, that takes also only one argument and the argument is not an array, then the other method is preferred. Examples:</p> <table class="wysiwyg-macro" data-macro-name="code" data-macro-default-parameter="java" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6amF2YX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>def foo(Object[] args) {1} def foo (x) {2} def foo (x,y} {3} assert foo() == 1 assert foo(1) == 2 assert foo(1,2) == 3 def x = [1,2] as Object[] assert foo(x) == 1 assert foo(1,1,1) == 1 </pre></td></tr></table> <p><strong><span style="text-decoration: underline;">Note:</span></strong> <code>T[]</code> or <code>T...</code> do have to be the last parameter, this clashes with Closures</p> <h2>Closures</h2> <p>See also <a class="confluence-link" href="/display/GROOVY/Closures" data-linked-resource-id="11403308" data-linked-resource-type="page" data-linked-resource-default-alias="Closures" data-base-url="http://docs.codehaus.org">Closures</a>.<br /> Groovy allows you to attach "blocks" to method calls like in:</p> <table class="wysiwyg-macro" data-macro-name="code" data-macro-default-parameter="java" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6amF2YX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>foo() { println it } </pre></td></tr></table> <p>To be able to attach a "block" in this way, the method signature must be <code><strong>def foo(p1, p2, ..., pn, T t)</strong></code>, where <code>T</code> is Object, Closure or no explicit type.</p> <p>Example: </p> <table class="wysiwyg-macro" data-macro-name="code" data-macro-default-parameter="Java" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6SmF2YX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>def foo(x,closure) {x+closure.call()} assert 1 == foo(1) {0} assert 2 == foo(1) {1} </pre></td></tr></table> <p>You are also allowed to use the "block" as normal argument </p> <table class="wysiwyg-macro" data-macro-name="code" data-macro-default-parameter="Java" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6SmF2YX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>foo(1,{1})</pre></td></tr></table> <p>If variable arguments and Closures are combined you will have the problem, that the closure needs to be the last argument, but the parameter enabling variable arguments needs to be the last one too. You could use code like this to check that at runtime: </p> <table class="wysiwyg-macro" data-macro-name="code" data-macro-default-parameter="java" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6amF2YX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>def foo(Object[] args) { if (!args || !(args[-1] instanceof Closure)) { throw new IllegalArgumentException("Last argument must be a closure") } ... } </pre></td></tr></table> <p> <code>!args</code> will be true if <code>args</code> is <code>null</code> or an array of length 0, <code>args[-1]</code> refers to the last element of the array.</p> <p><strong><span style="text-decoration: underline;">Note:</span></strong> the "block" is always the last argument</p> <h2>Named Arguments</h2> <p>See <a class="confluence-link" href="/display/GROOVY/Collections#Collections-Maps" data-anchor="Maps" data-linked-resource-id="2732" data-linked-resource-type="page" data-linked-resource-default-alias="Collections#Maps" data-base-url="http://docs.codehaus.org">Maps</a><br /> Named arguments requires the following method signature <code><strong>def foo(T t, p1, p2, ..., pn)</strong></code>, but the real work is done by the compiler where the the method call is defined. A method call <code><strong>foo(p1:e1, p2:e2, ..., pn:en, q1, q2, ..., qm)</strong></code> will always be transformed to <code><strong>foo([p1:e1, p2:e2, ..., pn:en], q1, q2, ..., qm)</strong></code>. If you mix the positions of the pi and qi elements, then the compiler will still force the same transformed signature.</p> <p>Example:</p> <table class="wysiwyg-macro" data-macro-name="code" data-macro-default-parameter="java" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6amF2YX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>def foo(x,y,z) {[x,y,z]} assert foo(a:1,b:2,3,4) == [[a:1, b:2], 3, 4] assert foo(a:1,3,b:2,4) == [[a:1, b:2], 3, 4] assert foo(3,4,a:1,b:2) == [[a:1, b:2], 3, 4] assert foo(4,3,b:2,a:1) == [[b:2, a:1], 4, 3] </pre></td></tr></table> <p>The type <code>T</code> can be Object, Map or no explicit type.</p> <p>(In fact other types are possible for <code>T</code>. Any type compatible to <code>[:].getClass()</code> can be used. But the type may change for example from HashMap (Groovy 1.0) to LinkedHashMap (since Groovy 1.5), so it is only safe to use the less specialized types.)</p> <p>Combining named arguments with closures or variable arguments is no problem. You can make the map the first element of the variable arguments part or you can let it have its own parameter: That is for you to decide. If you combine named arguments and closures, you will need two parameters. One for the map and one for the closure.</p> <p>In case of <code><strong>def foo(T t, p1, p2, ..., pn)</strong></code> all named arguments will be in <code>t</code>, but that also means that you can not make a method call where you access <code>pi</code> by name. Example </p> <table class="wysiwyg-macro" data-macro-name="code" data-macro-default-parameter="Java" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6SmF2YX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>def foo(x,y){} foo(x:1,y:2) </pre></td></tr></table> <p>This code will fail at runtime, because the method <code>foo</code> expects two arguments, but the map you gave is only one argument.</p> <p><strong><span style="text-decoration: underline;">Note:</span></strong> the map is always the first argument</p> <h2>Arguments with Default Values</h2> <p>Groovy supports also the usage of methods with default values for parameters. Any parameter <code>T t</code> can have a default value using <code>T t=x</code>, where x is the value. The usage of the default value is not bound to a special type. In fact this is a short form to declare an overloaded method. <code><strong>def foo(p1, p2, ..., pn, T t=x, q1, q2, ..., qm)</strong></code> becomes a method <code><strong>def foo(p1, p2, ..., pn, T t, q1, q2, ..., qm)</strong></code>, where <code>t</code> has no default value and a method <code><strong>def foo(p1, p2, ..., pn, q1, q2, ..., qm)</strong></code> this implementation:</p> <table class="wysiwyg-macro" data-macro-name="code" data-macro-default-parameter="java" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6amF2YX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>def foo(p1, p2, ..., pn, q1, q2, ..., qm) { // note: this is not working groovy code, just pseudo code! foo(p1, p2, ..., pn, x, q1, q2, ..., qm) }</pre></td></tr></table> <p>If multiple default values are used, then the parameter with the default value most right will be eliminated like seen here and the resulting method signature will be processed again. That means <code><strong>def foo(p1, p2, ..., pn, T t1=x, T t2=y, q1, q2, ..., qm)</strong></code> will first produce <code><strong>def foo(p1, p2, ..., pn, T t1, T t2, q1, q2, ..., qm)</strong></code> as the most general method and then continue the processing with <code><strong>def foo(p1, p2, ..., pn, T t1=x, q1, q2, ..., qm)</strong></code> which calls the other method and sets by using <code>y</code> for <code>t2</code>. since the signature still contains a default value the compiler will create <code><strong>def foo(p1, p2, ..., pn, q1, q2, ..., qm)</strong></code>, which calls the most general method using <code>x</code> for <code>t1</code> and <code>y</code> for {t2}}. This means if you use <code>n</code> default values, the compiler will produce <code>n+1</code> methods. You are not required to group the parameters with default values together in any way.</p> <p>Example:</p> <table class="wysiwyg-macro" data-macro-name="code" data-macro-default-parameter="java" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6amF2YX0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>def foo(x=1,y=2) {x+y} assert foo() == 3 assert foo(2) == 4 assert foo(5,10) == 15 </pre></td></tr></table> <p>You can combine default values with maps <code>def foo(Map m=[:],x,y)</code> to get optional named arguments, with closures <code>def foo(x,y,Closure c={})</code> to get optional closures and theoretically with variable arguments <code>def foo(x,y, Object[] args=[1,2])</code>, but there should be only rare cases where default arguments and variable arguments combined like this is making sense.</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