Groovy - tratamento de exceções

O tratamento de exceções é necessário em qualquer linguagem de programação para tratar os erros de tempo de execução de forma que o fluxo normal do aplicativo possa ser mantido.

A exceção normalmente interrompe o fluxo normal do aplicativo, que é a razão pela qual precisamos usar o tratamento de exceções em nosso aplicativo.

As exceções são amplamente classificadas nas seguintes categorias -

  • Checked Exception - As classes que estendem a classe Throwable, exceto RuntimeException e Error, são conhecidas como exceções verificadas, por exemplo ,IOException, SQLException etc. As exceções verificadas são verificadas em tempo de compilação.

Um caso clássico é FileNotFoundException. Suponha que você tenha o seguinte código em seu aplicativo que lê de um arquivo na unidade E.

class Example {
   static void main(String[] args) {
      File file = new File("E://file.txt");
      FileReader fr = new FileReader(file);
   } 
}

se o arquivo (file.txt) não estiver na unidade E, a seguinte exceção será gerada.

Capturado: java.io.FileNotFoundException: E: \ file.txt (O sistema não pode encontrar o arquivo especificado).

java.io.FileNotFoundException: E: \ file.txt (O sistema não pode localizar o arquivo especificado).

  • Unchecked Exception - As classes que estendem RuntimeException são conhecidas como exceções não verificadas, por exemplo, ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException etc. As exceções não verificadas não são verificadas em tempo de compilação, em vez disso, são verificadas em tempo de execução.

Um caso clássico é a ArrayIndexOutOfBoundsException, que acontece quando você tenta acessar um índice de uma matriz que é maior do que o comprimento da matriz. A seguir está um exemplo típico desse tipo de erro.

class Example {
   static void main(String[] args) {
      def arr = new int[3];
      arr[5] = 5;
   } 
}

Quando o código acima é executado, a seguinte exceção será gerada.

Pego: java.lang.ArrayIndexOutOfBoundsException: 5

java.lang.ArrayIndexOutOfBoundsException: 5

  • Error - O erro é irrecuperável, por exemplo, OutOfMemoryError, VirtualMachineError, AssertionError etc.

Esses são erros dos quais o programa nunca pode se recuperar e que farão com que o programa trave.

O diagrama a seguir mostra como a hierarquia de exceções no Groovy é organizada. É tudo baseado na hierarquia definida em Java.

Captura de exceções

Um método captura uma exceção usando uma combinação de try e catchpalavras-chave. Um bloco try / catch é colocado ao redor do código que pode gerar uma exceção.

try { 
   //Protected code 
} catch(ExceptionName e1) {
   //Catch block 
}

Todo o seu código que poderia gerar uma exceção é colocado no bloco de código protegido.

No bloco catch, você pode escrever um código personalizado para manipular sua exceção para que o aplicativo possa se recuperar da exceção.

Vejamos um exemplo do código semelhante que vimos acima para acessar um array com um valor de índice maior que o tamanho do array. Mas, desta vez, vamos envolver nosso código em um bloco try / catch.

class Example {
   static void main(String[] args) {
      try {
         def arr = new int[3];
         arr[5] = 5;
      } catch(Exception ex) {
         println("Catching the exception");
      }
		
      println("Let's move on after the exception");
   }
}

Quando executamos o programa acima, obteremos o seguinte resultado -

Catching the exception 
Let's move on after the exception

A partir do código acima, encerramos o código defeituoso no bloco try. No bloco catch, estamos apenas capturando nossa exceção e enviando uma mensagem de que ocorreu uma exceção.

Vários blocos de captura

Pode-se ter vários blocos catch para lidar com vários tipos de exceções. Para cada bloco catch, dependendo do tipo de exceção levantada, você escreveria o código para tratá-la de acordo.

Vamos modificar nosso código acima para capturar a ArrayIndexOutOfBoundsException especificamente. A seguir está o trecho de código.

class Example {
   static void main(String[] args) {
      try {
         def arr = new int[3];
         arr[5] = 5;
      }catch(ArrayIndexOutOfBoundsException ex) {
         println("Catching the Array out of Bounds exception");
      }catch(Exception ex) {
         println("Catching the exception");
      }
		
      println("Let's move on after the exception");
   } 
}

Quando executamos o programa acima, obteremos o seguinte resultado -

Catching the Aray out of Bounds exception 
Let's move on after the exception

No código acima, você pode ver que o bloco de captura ArrayIndexOutOfBoundsException é capturado primeiro porque significa o critério da exceção.

Finalmente Bloco

o finallybloco segue um bloco try ou um bloco catch. Um bloco final de código sempre é executado, independentemente da ocorrência de uma Exceção.

O uso de um bloco finally permite que você execute quaisquer instruções do tipo de limpeza que você deseja executar, não importa o que aconteça no código protegido. A sintaxe para este bloco é fornecida abaixo.

try { 
   //Protected code 
} catch(ExceptionType1 e1) { 
   //Catch block 
} catch(ExceptionType2 e2) { 
   //Catch block 
} catch(ExceptionType3 e3) { 
   //Catch block 
} finally {
   //The finally block always executes. 
}

Vamos modificar nosso código acima e adicionar o bloco finally de código. A seguir está o trecho de código.

class Example {
   static void main(String[] args) {
      try {
         def arr = new int[3];
         arr[5] = 5;
      } catch(ArrayIndexOutOfBoundsException ex) {
         println("Catching the Array out of Bounds exception");
      }catch(Exception ex) {
         println("Catching the exception");
      } finally {
         println("The final block");
      }
		
      println("Let's move on after the exception");
   } 
}

Quando executamos o programa acima, obteremos o seguinte resultado -

Catching the Array out of Bounds exception 
The final block 
Let's move on after the exception

A seguir estão os métodos de exceção disponíveis no Groovy -

public String getMessage ()

Retorna uma mensagem detalhada sobre a exceção que ocorreu. Esta mensagem é inicializada no construtor Throwable.

public Throwable getCause ()

Retorna a causa da exceção conforme representado por um objeto Throwable.

public String toString ()

Retorna o nome da classe concatenada com o resultado de getMessage ()

public void printStackTrace ()

Imprime o resultado de toString () junto com o rastreamento de pilha em System.err, o fluxo de saída de erro.

public StackTraceElement [] getStackTrace ()

Retorna uma matriz contendo cada elemento no rastreamento da pilha. O elemento no índice 0 representa o topo da pilha de chamadas e o último elemento da matriz representa o método na parte inferior da pilha.

public Throwable fillInStackTrace ()

Preenche o rastreamento da pilha deste objeto Throwable com o rastreamento da pilha atual, adicionando a qualquer informação anterior no rastreamento da pilha.

Exemplo

A seguir está o exemplo de código usando alguns dos métodos fornecidos acima -

class Example {
   static void main(String[] args) {
      try {
         def arr = new int[3];
         arr[5] = 5;
      }catch(ArrayIndexOutOfBoundsException ex) {
         println(ex.toString());
         println(ex.getMessage());
         println(ex.getStackTrace());  
      } catch(Exception ex) {
         println("Catching the exception");
      }finally {
         println("The final block");
      }
		
      println("Let's move on after the exception");
   } 
}

Quando executamos o programa acima, obteremos o seguinte resultado -

java.lang.ArrayIndexOutOfBoundsException: 5 
5 
[org.codehaus.groovy.runtime.dgmimpl.arrays.IntegerArrayPutAtMetaMethod$MyPojoMetaMet 
hodSite.call(IntegerArrayPutAtMetaMethod.java:75), 
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) ,
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) ,
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133) ,
Example.main(Sample:8), sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method),
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57),
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ,
java.lang.reflect.Method.invoke(Method.java:606),
org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93),
groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325),
groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1443),
org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:893),
groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:287),
groovy.lang.GroovyShell.run(GroovyShell.java:524),
groovy.lang.GroovyShell.run(GroovyShell.java:513),
groovy.ui.GroovyMain.processOnce(GroovyMain.java:652),
groovy.ui.GroovyMain.run(GroovyMain.java:384),
groovy.ui.GroovyMain.process(GroovyMain.java:370),
groovy.ui.GroovyMain.processArgs(GroovyMain.java:129),
groovy.ui.GroovyMain.main(GroovyMain.java:109),
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method),
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57),
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ,
java.lang.reflect.Method.invoke(Method.java:606),
org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:109),
org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:131),
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method),
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57),
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ,
java.lang.reflect.Method.invoke(Method.java:606),
com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)]
 
The final block 
Let's move on after the exception