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>We can examine classes in Groovy to find out information in the form of strings.</p> <h3>Examining Classes</h3> <p>To find out a class's name and superclasses:</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{} assert A.name == 'A' assert new A().class.name == 'A' assert A.class.name == 'A' //'class' is optionally used here class B extends A{} assert B.name == 'B' class C extends B{} def hierarchy= [] def s = C while(s != null){ hierarchy << s.name; s= s.superclass } assert hierarchy == [ 'C', 'B', 'A', 'java.lang.Object' ] </pre></td></tr></table> <p>To examine the interfaces:</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> interface A1{} interface A2{} class A implements A1, A2{} def interfacesA = [] as Set //use a set because interfaces are unordered A.interfaces.each{ interfacesA << it.name } assert interfacesA == [ 'A1', 'A2', 'groovy.lang.GroovyObject' ] as Set interface B1{} class B extends A implements B1{} def interfacesB = [] as Set B.interfaces.each{ interfacesB << it.name } assert interfacesB == [ 'B1' ] as Set //only immediately implemented interfaces are reported </pre></td></tr></table> <p>We can check if a class is a class or an interface:</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 Observer.isInterface() assert ! Observable.isInterface() </pre></td></tr></table> <p>We can examine public fields and their types:</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 adyn //if no modifier, field is private String astr public apdyn public String apstr protected aqdyn } interface B1{} interface B2{} class B extends A implements B1, B2{ def bdyn int bint public bpdyn public int bpint protected bqdyn } def dets = [] as Set B.fields.each{ //public fields only dets << [ it.name, it.type.name ] //name of field and name of type } assert dets == [ [ 'apstr', 'java.lang.String' ], [ 'apdyn', 'java.lang.Object' ], [ 'bpint', 'int' ], [ 'bpdyn', 'java.lang.Object' ], [ '__timeStamp', 'java.lang.Long' ], //added by Groovy ] as Set </pre></td></tr></table> <p>We can look at a certain field of a class:</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 Math.fields.name as Set == [ 'E', 'PI' ] as Set assert Math.class.getField('PI').toString() == 'public static final double java.lang.Math.PI' assert Math.class.getField('PI').getDouble() == 3.141592653589793 //we must know the type of the value </pre></td></tr></table> <p>We can also look at the constructors and methods of a class:</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 HashMap.constructors.collect{ it.parameterTypes.name } as Set == [ ['int'], [], ['java.util.Map'], ['int', 'float'] ] as Set GroovyObject.methods.each{ println it } //to print full details of each method of a class assert GroovyObject.methods.name as Set == ['invokeMethod', 'getMetaClass', 'setMetaClass', 'setProperty', 'getProperty'] as Set assert GroovyObject.getMethod('getMetaClass').toString() == 'public abstract groovy.lang.MetaClass groovy.lang.GroovyObject.getMetaClass()' </pre></td></tr></table> <p>Some code to find out all the getters for a class:</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> getters= { it.methods.name.findAll{ it =~ /^get[A-Z]/ }. collect{ it[3].toLowerCase()+it[4..-1] }.join(', ') } assert getters( GroovyObject ) == 'metaClass, property' </pre></td></tr></table> <p>To see all nested classes for a particular class (eg, of Character):</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 Character.classes.name as Set == [ 'java.lang.Character$Subset', 'java.lang.Character$UnicodeBlock' ] as Set </pre></td></tr></table> <p>To query a particular nested class (eg, Character.UnicodeBlock):</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> Character.UnicodeBlock.fields.name.each{ println it } //to list all public constants </pre></td></tr></table> <h3>Reflecting the Reflection classes themselves</h3> <p>We can use reflection on the reflection classes themselves. 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> assert Class.methods[0].class == java.lang.reflect.Method //find the class of any method of any class... java.lang.reflect.Method.methods.each{ println it.name } //...then find its method names... //...to help us build a custom-formatted listing of method details HashMap.class.methods.each{ println """$it.name( ${it.parameterTypes.name.join(', ')} ) returns \ $it.returnType.name ${it.exceptionTypes.size()>0?'throws ':''}\ ${it.exceptionTypes.name.join(', ')}""" } </pre></td></tr></table> <p>We can look at the modifiers of methods and 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> import java.lang.reflect.Modifier Modifier.methods.name.sort{}.each{ println it } //use reflection on the reflection classes themselves... //...to help us build a custom-formatted listing of modifier details [ (ArrayList.getMethod( 'remove', [Object] as Class[] )): [ 'public' ] as Set, (Collections.getMethod( 'synchronizedList', [List] as Class[] )): [ 'public', 'static' ] as Set, (Math): [ 'public', 'final' ] as Set, (ClassLoader): [ 'public', 'abstract' ] as Set, ].each{ key, val-> def m= key.modifiers def mods= [ ({Modifier.isPublic(it)}): 'public', ({Modifier.isProtected(it)}): 'protected', ({Modifier.isPrivate(it)}): 'private', ({Modifier.isInterface(it)}): 'interface', ({Modifier.isAbstract(it)}): 'abstract', ({Modifier.isFinal(it)}): 'final', ({Modifier.isStatic(it)}): 'static', ({Modifier.isVolatile(it)}): 'volatile', ({Modifier.isNative(it)}): 'native', ({Modifier.isStrict(it)}): 'strict', ({Modifier.isSynchronized(it)}): 'synchronized', ({Modifier.isTransient(it)}): 'transient', ].collect{ k, v-> k(m)? v: null } as Set mods.removeAll( [null] ) assert mods == val } </pre></td></tr></table> <h3>Manipulating Objects</h3> <p>When a class is unknown at compile time (eg, we only have a string representation of a class name), we can use reflection to create objects:</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 Class.forName("java.util.HashMap").newInstance() == [:] def constructor = Class.forName("java.util.HashMap"). getConstructor( [ int, float ] as Class[] ) assert constructor.toString() == 'public java.util.HashMap(int,float)' assert constructor.newInstance( 12, 34.5f ) == [:] </pre></td></tr></table> <p>We can examine and change public fields for a class refering using a String for the name:</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{ public value1 protected value2 A( int v ){ value1= v; value2 = v } } def a= new A( 100 ) assert A.getField( 'value1' ).get( a ) == 100 //public fields only try{ A.getField( 'value2' ).get( a ); assert false } catch(Exception e){ assert e instanceof NoSuchFieldException } A.getField( 'value1' ).set( a, 350 ) assert a.value1 == 350 </pre></td></tr></table> <p>And we can call methods using a string for the name:</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 String.getMethod( 'concat', [ String ] as Class[] ). invoke( 'Hello, ', [ 'world!' ] as Object[] ) == 'Hello, world!' </pre></td></tr></table> <h3>Working with Arrays</h3> <p>We can examine and manipulate arrays. To enquire the public array fields of a class:</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{ public boolean alive public int[] codes public Date[] dates protected boolean[] states } //find all public array fields def pubFields= new A().class.fields.findAll{ it.type.isArray() }. collect{ [it.name, it.type.name] } assert pubFields == [ [ 'codes', '[I' ], //'[I' means array of int [ 'dates', '[Ljava.util.Date;' ], //means array of object java.util.Date ] </pre></td></tr></table> <p>To enquire the component type/s of an array:</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', 'int' ], (Date[]): [ '[Ljava.util.Date;', 'java.util.Date' ], (new Date[6].class): [ '[Ljava.util.Date;', 'java.util.Date' ], //instantiated class (String[][]): [ '[[Ljava.lang.String;', '[Ljava.lang.String;' ], ].each{ k, v -> assert [ k.name, k.componentType.name ] == v } </pre></td></tr></table> <p>We can create and copy arrays when their component type and size is unknown at compile time:</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.lang.reflect.Array def a1 = [55, 66] as int[] //component type and size unknown at compile time... def a2 = Array.newInstance( a1.class.componentType, a1.size() * 2 ) assert a2.class.componentType == int assert a2.size() == 4 System.arraycopy( a1, 0, a2, 0, a1.size() ) assert a2 as List == [55, 66, 0, 0] as List </pre></td></tr></table> <p>We can create multi-dimensional arrays in a similar way, where component type and array sizes can be unknown at compile time:</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.lang.reflect.Array //assertion checking code... assert1D= {x,y-> assert x.size() == y.size() for( int i: x.size() - 1 ) assert x[ i ] == y[ i ] } assert2D= {x,y-> assert x.size() == y.size() for( int i: x.size() - 1 ){ assert x[ i ].size() == y[ i ].size() for( int j: x[ i ].size() - 1 ) assert x[ i ][ j ] == y[ i ][ j ] } } //each is a 1-D int array with 3 elts def a0= new char[ 3 ] def a1= Array.newInstance( char, 3 ) def a2= Array.newInstance( char, [ 3 ] as int[] ) assert1D( a0, a1 ) assert1D( a0, a2 ) //both are a 2-D 3x4 array of String elts def b0= new String[3][4] def b1= Array.newInstance( String, [ 3, 4 ] as int[] ) assert2D( b0, b1 ) //both are a 2-D array of 6 char arrays, with undefined tail dimension def c0 = new char[6][] def c1 = Array.newInstance( char[], [ 6 ] as int[] ) assert1D( c0, c1 ) </pre></td></tr></table> <p>We can use set() and get() to copy the contents of one array index to another:</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.lang.reflect.Array def a= [ 12, 78 ] as int[], b= new int[ 4 ] Array.set( b, 0, Array.get( a, 0 ) ) assert b[ 0 ] == 12 </pre></td></tr></table> <p>This tutorial is loosely based on Sun's tutorial on Java Reflection, but using Groovy code instead.</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