Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

Exceptions and Errors are together known as Throwables. The Throwables are positioned like so in the Object hierarchy:

Code Block

java.lang.Object
  java.lang.Throwable
    java.lang.Error
    java.lang.Exception

Errors are fatalities that we would normally want to cause a program failure, while Exceptions are events that we would normally want to handle in our program. An example of using them with a try-catch statement, a 'try' clause followed by a 'catch' clause:

Code Block

//assert 1 == 0 //AssertionError when uncommented

//try{ assert 1 == 0 }catch(e){}
    //AssertionError when uncommented: Exceptions, not Errors, are caught here

try{
  assert 1 == 0
}catch(Error e){}
    //by specifying Error, prevents bad assertion from causing program failure

try{
  assert 1 == 0
}catch(Throwable e){} //specifying Throwable also prevents program failure

//try{ assert 1 == 0 }catch(Object o){}
    //compile error when uncommented:
    //only Throwables and its subclasses may be caught

A common idiom for asserting for exceptions is:

Code Block

try{
  'moo'.toLong() //this will generate an exception
  assert false //asserting that this point should never be reached
}catch(e){
  assert e in NumberFormatException
}

Some common exceptions associated with Groovy:

Code Block

assert new java.lang.ArithmeticException()
assert new java.lang.ArrayIndexOutOfBoundsException()
assert new java.lang.NullPointerException()
assert new java.io.IOException()

We can put code within a 'finally' clause following a matching 'try' clause, so that if regardless of whether the code in the 'try' clause throws an exception, the code in the finally clause will always execute:

Code Block

def z
try{
  def i= 7, j= 0
  try{
    def k= i / j
    assert false //never reached due to Exception in previous line
  }finally{
    z= 'reached here' //always executed even if Exception thrown
  }
}catch(e){
  assert e in ArithmeticException
  assert z == 'reached here'
}

We can attach more than one 'catch' clause to a 'try' clause, and attach a 'finally' clause also:

Code Block

class E1 extends Exception{} //we can define our own exceptions
class E2 extends Exception{}
class E3 extends Exception{}

try{
  def z

  //multi-catch try-block with finally-clause...
  try{
    throw new E2()
    assert false
  }catch(E1 e){
    assert false
  }catch(E2 e){
    z= 'reached here'
    throw new E3() //uncaught exception because only one catch clause executed
  }catch(E3 e){
    assert false //never reached
  }finally{
    assert z == 'reached here'
    throw new E1()
    assert false
  }

}catch(E1 e){} //catches exception thrown in embedded finally clause

With the multi catch block (since Groovy 2.0), we’re able to define several exceptions to be catch and treated by the same catch block.

Code Block
languagegroovy
try {
    /* ... */
}catch(IOException | NullPointerException e) {
    /* one block to handle 2 exceptions */
}

An exception will ripple up through the nested blocks, executing only code in 'finally' clauses, until caught, or the thread terminates.

Code Block

class MyException extends Exception{}
def z
try{
  try{
    throw new MyException()
    assert false
  }finally{}
}catch(e){
  assert e in MyException
  z= 'been here'
}
assert z == 'been here'

Exceptions will also ripple through function and method invocations

Code Block

class MyException extends Exception{}

def z= []
def met(){
  throw new MyException()
}
try{ met(); assert false }
catch(e){assert e in MyException; z << 'function'}

class M{
  def m(){ throw new MyException() }
}
try{ new M().m(); assert false }
catch(e){assert e in MyException; z << 'method' }

def c= { throw new MyException() }
try{ c(); assert false }
catch(e){assert e in MyException; z << 'closure'}

assert z == ['function', 'method', 'closure']

//Method embedded in closure...
def z2
def d= { new M().m(); assert false }
try{ d(); assert false }
catch(e){assert e in MyException; z2= 'closure d'}
assert z2 == 'closure d'

We can mark a function or method indicating what type of Exception it might throw. This is a useful documentation feature:

Code Block

class MyException extends Exception{}
def z= []

def met() throws MyException{ // 'function met() may throw MyException'
  throw new MyException()
}
try{ met(); assert false }
catch(e){assert e in MyException; z << 'function'}

class M{
  def m() throws MyException{ // 'method m() of class M may throw MyException'
    throw new MyException()
  }
}
try{ new M().m(); assert false }
catch(e){assert e in MyException; z << 'method' }

assert z == ['function', 'method']