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><strong>Note: This page may not follow the explanations from the JLS.</strong></p><p>Java has two basic informal rules for scoping:</p><p><strong>Principle #1</strong>: "A variable is only visible in the block it is defined in and in nested blocks".<br /> <strong>Principle #2</strong>: "A variable can't be visible more than one time".</p><p>Java does know classwide variables and local variables. Local variables are defined as method parameter or inside the method block. Classwide variables are defined as attributes of the class. Of course Java does violate this first principle I showed at top here a little since I can access class wide varibales from outside the class, if the access modifier is for example public. A local variable of the same name as an attribute does not violate the second principle, as the attribute is hidden by the local variable and with this no longer visible without using a qualifier like "this".</p><h2>Now, what about Groovy?</h2><p>In Groovy we also have these two principles, but since we have different constructs, we may lay out these principles in a different way. Let us start with local variables.</p><ul><li>In Groovy you are neither allowed to define two local variables of the same name, just like in Java.</li><li>You are allowed to hide an attribute by defining a local variable of the same name, just like in Java.</li></ul><h2>So what is different?</h2><p>Scripts are. When you define a variable in a script it is always local. But methods are not part of that scope. So defining a method using different variables as if they were attributes and then defining these variables normally in the script leads to problems. Example:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="title=Example of disallowed definition in scripts" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6dGl0bGU9RXhhbXBsZSBvZiBkaXNhbGxvd2VkIGRlZmluaXRpb24gaW4gc2NyaXB0c30&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>String attribute = "bar" void aMethod(){ assert attribute == "bar" // Not allowed ! } aMethod() </pre></td></tr></table><p>Executing this code you get an exception talking about a missing property or field.</p><p>The only things the method has access to are:</p><ul><li>the binding,</li><li>attributes defined by the base class, and</li><li>the dynamic properties defined by the MetaClass (explanations for these will follow).<br /> "attribute" here is no field, no property, no dynamic defined property and not part of the binding.</li></ul><h2>When is something in the Binding and when not?</h2><p>That's easy. When it is not defined, it is in the binding.</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 localVar = "I am a local variable" bindingVar = "I am a binding variable" </pre></td></tr></table><p>The trick is - and that is admittedly not easy for Java programers - to <strong>not</strong> to define the variable before using it, and it will go into the binding. Any defined variable is local. <strong>Please note: the binding exists only for scripts.</strong></p><h2>What is this "def" I heard of?</h2><p>"def" is a replacement for a type name. In variable definitions it is used to indicate that you don't care about the type. In variable definitions it is mandatory to either provide a type name explicitly or to use "def" in replacement. This is needed to the make variable definitions detectable for the Groovy parser.</p><p>These definitions may occur for local variables in a script or for local variables and properties/fields in a class.</p><table class="wysiwyg-macro" data-macro-name="tip" data-macro-parameters="title=Rule of thumb" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e3RpcDp0aXRsZT1SdWxlIG9mIHRodW1ifQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="RICH_TEXT"><tr><td class="wysiwyg-macro-body"><p>You can think of "def" as an alias of "Object" and you will understand it in an instant.</p></td></tr></table><p>"def" can also replace "void" as the return type in a method definiton.</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 dynamic = 1 dynamic = "I am a String stored in a variable of dynamic type" int typed = 2 typed = "I am a String stored in a variable of type int??" // throws ClassCastException </pre></td></tr></table><p>The assignment of a string, to a variable of type int will fail. A variable typed with "def" allows this.</p><h2>A Closure is a block</h2><p>In the terms of the principles above a closure is a block. A variable defined in a block is visible in that block and all blocks that are defined in that block. For example in Java:</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="title=a Java block" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6dGl0bGU9YSBKYXZhIGJsb2NrfQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>{ int i=1; { System.out.println (i); } } </pre></td></tr></table><p>Such a block may be defined freely as in the example above, or by loops, synchronized statements, try-catch, switch, ... all that has "{".</p><p>In Groovy we have an additonal structure with "{", the closure. To follow the principles above, it is not allowed to define two variables of the same name in a closure.</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="title=Not allowed" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6dGl0bGU9Tm90IGFsbG93ZWR9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>def closure = { int i; int i } </pre></td></tr></table><p>And of course, the same for combinations with nested closures.</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="title=invalid double definition of variables" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6dGl0bGU9aW52YWxpZCBkb3VibGUgZGVmaW5pdGlvbiBvZiB2YXJpYWJsZXN9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>def outer = { int i def inner = { int i } } </pre></td></tr></table><p>A block ends with its corresponding "}". So it is allowed to reuse that name later in a different block.</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="title=Allowed" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6dGl0bGU9QWxsb3dlZH0&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>def closure1 = { parameter -> println parameter } def closure2 = { parameter -> println parameter } </pre></td></tr></table><p>Both closures define a local varibale named "parameter", but since these closures are not nested, this is allowed. <strong>Note: unlike early versions of Groovy and unlike PHP, a variable is visible in the block, not outside. Just like in Java.</strong></p><h2>And "it"?</h2><p>"it" is a special variable name, that is defined automatically inside a closure. It refers always to the first parameter of the closure, or null, if the closure doesn't have any parameters.</p><table class="wysiwyg-macro" data-macro-name="code" data-macro-parameters="title=implicit it in closures" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGU6dGl0bGU9aW1wbGljaXQgaXQgaW4gY2xvc3VyZXN9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre>def c = { it } assert c() == null assert c(1) == 1 </pre></td></tr></table><p>When using nested cosures (closures in closures) the meaning of "it" depends on the closure you are 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 outer = { def inner = { it+1 } inner(it+1) } assert outer(1) == 3 </pre></td></tr></table><p>You see, that "it" is used two times, the "it" in "inner" means the first parameter of the closure "inner", the following "it" means the first parameter of "outer". This helps a lot when copying code from one place to another containing closure that are using it.</p><h2>The keyword "static"</h2><p>"static" is a modifier for attributes (and methods, but this is not at issue here). It defines the "static scope". That means all variables not defined with "static" are not part of that static scope and as such not visible there. There is no special magic to this in Groovy. So for an explanation of "static" use any Java book.</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