ResumosMIEI

Uma coleção de resumos, para ajudar os que precisam daquele empurrão.


Project maintained by mendess Hosted on GitHub Pages — Theme by mattgraham

Exceptions

Exceptions são uma ferramenta usada para realizar controlo de erros. Enquanto que em C quase todos os erros que ocorrem dão origem a uma Segmentation Fault genérica, quando trabalhamos com uma linguagem orientada a objetos é costume usar exceptions que transmitem mais informação.

Tipos de exceptions

A classe abstrata que todos os erros e exceções devem estender é Throwable. Depois desta temos 2 sub-tipos:

Exceptions mais comuns

A exceção mais comum é NullPointerException que ocorre sempre que se tenta aceder a uma variável cujo valor seja null.

Exemplo:

1 public class ExampleClass{
2     public static void main(String[] args){
3         String s = null;
4         System.out.println(s.length());
5     }
6 }

Irá produzir o seguinte output no terminal:

Exception in thread "main" java.lang.NullPointerException
    at ExampleClass.main(ExampleClass.java:4)

Como podemos ver o nome completo da exception é java.lang.NullPointerException, a classe em que ocorreu e o método ExampleClass.main e o ficheiro e respetiva linha de código ExampleClass.java:4

Propagação de exceções por métodos

Quando uma exceção ocorre, se não for tratada, ira interromper a execução do método imediatamente e subir até que atinja um ponto em que seja tratada ou que não possa subir mais, o que normalmente faz com que o programa termine, como foi o caso do exemplo anterior.

  1 public class ExampleClass{
  2     public static void main(String[] args){
  3         String s = null;
  4         System.out.println("Hello");
  5         printStringLength(s);
  6         System.out.println("Still running");
  7     }
  8     public static void printStringLength(String s){
  9         System.out.print(s.length());
 10         System.out.println(" characters");
 11     }
 12 }

Irá produzir o seguinte output no terminal:

Hello
Exception in thread "main" java.lang.NullPointerException
    at ExampleClass.printStringLength(ExampleClass.java:9)
    at ExampleClass.main(ExampleClass.java:5)

Como podemos ver a exceção gerada no método printStringLength originou na linha 9 e, como consequência, a linha 10 não foi executada. Da mesma forma a linha 6 da main() não foi executada pois a exceção foi propagada para esta. Como neste ponto a exceção não foi tratada causou a interrupção por completo do programa.

Try/catch

Para tratar uma exceção temos ao nosso dispor a sintaxe do try{}catch().

try{
    /* try block: código que possa produzir uma exceção */
} catch (NullPointerException e) {
    /* catch block: tratar exceção */
}
/* Resto do método */

Assim sempre que código dentro do try block lançar uma NullPointerException ira imediatamente saltar para o catch block e depois continuar pelo /*Resto do método*/ sem que o interrompa.

Aplicando isto ao exemplo anterior:

  1 public class ExampleClass{
  2     public static void main(String[] args){
  3         String s = null;
  4         System.out.println("Hello");
  5         printStringLength(s);
  6         System.out.println("Still running");
  7     }
  8     public static void printStringLength(String s){
  9         try{
 10             System.out.print(s.length());
 11         }catch(NullPointerException e){
 12             System.out.print("0");
 13         }
 14         System.out.println(" characters");
 15     }
 16 }

Irá produzir o seguinte output no terminal:

Hello
0 characters
Still running

Como podemos ver todas as linhas de código foram executadas apesar da exceção ter sido lançada pela linha 10.

Criar uma nova exceção

Muitas vezes a nossa aplicação tem os seus erros específicos que tem de tratar, nesse caso será boa ideia criar as nossas próprias exceções.

Uma exceção é um objeto, e como todos os objetos é definido por uma classe.

public class MyException extends Exception{

}

Isto é suficiente para criar uma exceção simples. A invocação do super está implícita.

Para lançar esta exceção, assim como qualquer outra, usamos a keyword throw.

public method() throws MyException{
    /* code */
    if(someError){
        throw new MyException();
    }
    /* more code */
}

Um throw tem o mesmo impacto na execução que um return, ou seja, se um throw for executado o método termina. Para além disto, se se tratar de uma Checked Exception, tem de se sinalizar na assinatura do método que este lança uma exceção, para que quem o use esteja ciente dessa possibilidade e possa tratar o erro.

A Classe Throwable

A classe Throwable é a superclasse de todas as exceções e erros, apenas classes que estendam Throwable podem ser lançadas por um throw e tratadas por um catch.

A nossa exceção pode ter qualquer construtor que seja necessário, no entanto, seguir os construtores implementados pela classe Throwable é o mais comum.

Exemplo

public class MyException extends Exception{

    public MyException(){ // Se não incluirmos este constructor a nossa
    }                     // exceção terá de ter sempre uma mensagem

    public MyException(String message){
        super(message);
    }
}

Fazendo assim uso de um dos construtores da super classe.

public method() throws MyException{
    /* code */
    if(someError){
        throw new MyException("Exceção feia :(");
    }
    /* more code */
}