Table of contents
- Foreword;
- Semicolon;
- Return;
- Default visibility;
- Safe navigation operator;
- Boolean evaluation;
- Elvis operator;
- Exception handling;
Foreword
I started working at new company recently and encountered that Groovy is used for various non-performance critical tasks here. I follow the principle that leaky abstractions should be avoided whenever possible, hence, it's a time to learn Groovy.
Couple of words about it - Groovy is a dynamic language that provides concise syntax and metaprogramming facilities, is executed under JVM and completely interoperable with java code, i.e. it's possible either to use groovy from java or java from groovy. The only drawback I see for now is performance aspect - groovy heavily uses reflection, type-checks, exception-based processing. However, that may be the tool of choice for application prototyping and various support tasks like buildmastering.
I'm going to highlight groovy faetures that are the most significant for java developers that want to get familiar with groovy.
Next part - Groovy features, part 2 - java beans
Semicolon
Semicolon is almost optional in Groovy. You can use it to separate the statements if necessary. I.e. following groovy script works just fine
print('hello, ')
println('world')
print('hello '); println('one more time')
Return
'return' keyword is optional:
def test(i) { i > 0 }
value = 4
printf('%d is %spositive%n', value, test(value) ? '' : 'not ')
Default visibility
Methods and classes are public by default in groovy:
package org.denis
class GroovyTestClass {
def test() { println 'test' }
}
projects/java/test/target$ javap org.denis.GroovyTestClass
Compiled from "GroovyTestClass.groovy"
public class org.denis.GroovyTestClass extends java.lang.Object implements groovy.lang.GroovyObject{
public static final java.lang.Class $ownClass;
public static java.lang.Long __timeStamp;
public static java.lang.Long __timeStamp__239_neverHappen1271752231139;
public org.denis.GroovyTestClass();
public java.lang.Object test();
protected groovy.lang.MetaClass $getStaticMetaClass();
public groovy.lang.MetaClass getMetaClass();
public void setMetaClass(groovy.lang.MetaClass);
public java.lang.Object invokeMethod(java.lang.String, java.lang.Object);
public java.lang.Object getProperty(java.lang.String);
public void setProperty(java.lang.String, java.lang.Object);
static {};
public void super$1$wait();
public java.lang.String super$1$toString();
public void super$1$wait(long);
public void super$1$wait(long, int);
public void super$1$notify();
public void super$1$notifyAll();
public java.lang.Class super$1$getClass();
public java.lang.Object super$1$clone();
public boolean super$1$equals(java.lang.Object);
public int super$1$hashCode();
public void super$1$finalize();
static java.lang.Class class$(java.lang.String);
}
You can see that either GroovyTestClass or GroovyTestClass.test() visibility is public.
Safe navigation operator
Groovy offers convenient operator '?.' - it is used with object references for checking that it's not null, i.e. it returns null if it's applied to null or proceeds to the target method instead:
class Address {
def street
}
class User {
def name
def address
}
user1 = new User(name: 'Guy', address: new Address(street: 'Reg Lights District'))
user2 = new User()
println 'Processing user1'
println user1.address.street
println user1.name
println 'Processing user2 with ?.'
println user2?.address?.street
println user2?.name
println 'Processing user2 without ?.'
println user2.address.street
Output:
Processing user1
Reg Lights District
Guy
Processing user2 with ?.
null
null
Processing user2 without ?.
Caught: java.lang.NullPointerException: Cannot get property 'street' on null object
at GroovyTest.run(GroovyTest.groovy:22)
Boolean evaluation
Groovy provides special rules for using objects of various types at boolean context:
def test(value, description) {
evaluationResult = value ? true : false;
printf "%s '%s' evaluates to %b%n", description, value, evaluationResult
}
test(true, 'boolean value')
test(false, 'boolean value')
test(null, 'null reference')
test(new Object(), 'non-null reference')
test([], 'empty list')
test([1], 'non-empty list')
test([:], 'empty map')
test([1: 2], 'non-empty map')
test('', 'empty char sequence')
test('xxx', 'non-empty char sequence')
test([].iterator(), 'empty iterator')
test([1].iterator(), 'non-empty iterator')
test(new Properties().elements(), 'empty enumeration')
test(System.properties.elements(), 'non-empty enumeration')
test([1].iterator(), 'non-empty iterator')
test(0.01, 'none-zero number double value')
test(0, 'zero number double value')
test('test' =~ /es/, 'matcher with at least one match')
test('test' =~ /se/, 'matcher with no match')
Output:
boolean value 'true' evaluates to true
boolean value 'false' evaluates to false
null reference 'null' evaluates to false
non-null reference 'java.lang.Object@51e67ac' evaluates to true
empty list '[]' evaluates to false
non-empty list '[1]' evaluates to true
empty map '{}' evaluates to false
non-empty map '{1=2}' evaluates to true
empty char sequence '' evaluates to false
non-empty char sequence 'xxx' evaluates to true
empty iterator 'java.util.AbstractList$Itr@1d2c5431' evaluates to false
non-empty iterator 'java.util.AbstractList$Itr@494b6bed' evaluates to true
empty enumeration 'java.util.Hashtable$EmptyEnumerator@24ebf068' evaluates to false
non-empty enumeration 'java.util.Hashtable$Enumerator@2a313170' evaluates to true
non-empty iterator 'java.util.AbstractList$Itr@3a4c5b4' evaluates to true
none-zero number double value '0.01' evaluates to true
zero number double value '0' evaluates to false
matcher with at least one match 'java.util.regex.Matcher[pattern=es region=0,4 lastmatch=es]' evaluates to true
matcher with no match 'java.util.regex.Matcher[pattern=se region=0,4 lastmatch=]' evaluates to false
Elvis operator
There is a short form of ternary operator - '?:'. It works as follows - use left operand if it evaluates to true; use right operand otherwise:
println([]?: 'empty array')
println(null?: 'null reference')
println(''?: 'empty char sequence')
println([1]?: 'empty array')
println(new Object()?: 'null reference')
println('xxx'?: 'empty char sequence')
Output:
empty array
null reference
empty char sequence
[1]
java.lang.Object@1408a92
xxx
Exception handling
Groovy doesn't require to handle checked exceptions. Another feature is that it's possible to use more concise syntax for catching all Exceptions:
class Test {
def test() {
// Not obliged to declare the exception at method signature
throw new IOException()
}
}
test = new Test()
try {
test.test()
} catch (ex) { // Only Exception are handled here, all Errors and Throwable are popped up to the stack
println 'Exception is caught: ' + ex
}

0 comments:
Post a Comment