# Exceções

O mecanismo de manipulação de exceções em Java, embora apresente suas particularidades, teve seu projeto inspirado no mecanismo equivalente de C++, que por sua vez foi inspirado em Ada. Uma exceção é um sinal que indica que algum tipo de condição excepcional ocorreu durante a execução do programa. Assim, exceções estão associadas a condições de erro que não tinham como ser veriﬁcadas durante a compilação do programa.
As duas atividades associadas à manipulação de uma exceção são:

## geração

    a sinalização de que uma condição excepcional (por exemplo, um erro) ocorreu, e

## captura

    a manipulação (tratamento) da situação excepcional, onde as ações necessárias para a recuperação da situação de erro são deﬁnidas.
Para cada exceção que pode ocorrer durante a execução do código, um bloco de ações de tratamento (um exception handler) deve ser especiﬁcado. O compilador Java veriﬁca e força que toda exceção “não-trivial” tenha um bloco de tratamento associado.
A exceção provê um mecanismo adequado à manipulação de erros síncronos, para situações onde a recuperação do erro é possível. A sinalização da exceção é propagada a partir do bloco de código onde ela ocorreu através de toda a pilha de invocações de métodos, até que a exceção seja capturada por um bloco manipulador de exceção. Eventualmente, se tal bloco não existir em nenhum ponto da pilha de invocações de métodos, a sinalização da exceção atinge o método main, fazendo com que o interpretador Java apresente uma mensagem de erro e aborte sua execução.

## Tratamento de exceções

A captura e o tratamento de exceções em Java se dá através da especiﬁcação de blocos try, catch e finally, deﬁnidos através destas mesmas palavras reservadas da linguagem. A estruturação desses blocos obedece à seguinte sintaxe:
sendo:

### bloco normal

    código que inclui comandos/invocações de métodos que podem gerar uma situação de exceção, sem nenhum tratamento de erro. É o chamado cenário cor-de-rosa, que supõe a execução completa sem ocorrência de nenhuma situação de erro;

### erros x

    bloco de tratamento associado à condição de exceção XException ou a qualquer uma de suas subclasses, identificada aqui pelo objeto com referência ex;

### erros y

    bloco de tratamento para a situação de exceção YException ou a qualquer uma de suas subclasses;

### bloco final

    código que sempre será executado após o bloco try, independentemente de sua conclusão ter ocorrido normalmente ou ter sido interrompida por alguma condição de exceção.
XException e YException deveriam ser substituídos pelo nome do tipo de exceção. Os blocos não podem ser separados por outros comandos — um erro de sintaxe seria detectado pelo compilador Java neste caso. Cada bloco try pode ser seguido por zero ou mais blocos catch; dois blocos catch com o mesmo corpo podem ser combinados usando o formato multicatch, como em
O bloco finally, quando presente, é sempre executado. Em geral, ele inclui comandos que liberam recursos que eventualmente possam ter sido alocados durante o processamento do bloco try e que podem ser liberados, independentemente de a execução ter encerrado com sucesso ou ter sido interrompida por uma condição de exceção. A presença desse bloco é opcional.
Alguns exemplos de exceções já deﬁnidas no pacote java.lang incluem:

### ArithmeticException

    indica situações de erros em processamento aritmético, tal como uma divisão inteira por 0. A divisão de um valor real por 0 não gera uma exceção (o resultado é o valor inﬁnito);

### NumberFormatException

    indica que tentou-se a conversão de uma string para um formato numérico, mas seu conteúdo não representava adequadamente um número para aquele formato. É uma subclasse de IllegalArgumentException;

### IndexOutOfBounds

    indica a tentativa de acesso a um elemento de um agregado aquém ou além dos limites válidos. É a superclasse de ArrayIndexOutOfBoundsException, para arranjos, e de StringIndexOutOfBounds, para strings;

### NullPointerException

    indica que a aplicação tentou usar uma referência a um objeto que não foi ainda deﬁnida;

### ClassNotFoundException

    indica que a máquina virtual Java tentou carregar uma classe mas não foi possível encontrá-la durante a execução da aplicação.
Além disso, outros pacotes especiﬁcam suas exceções, referentes às suas funcionalidades. Por exemplo, no pacote java.io deﬁne-se IOException, que indica a ocorrência de algum tipo de erro em operações de entrada e saída. É a superclasse para condições de exceção mais especíﬁcas desse pacote, tais como EOFException (ﬁm de arquivo ou stream), FileNotFoundException (arquivo especiﬁcado não foi encontrado) e InterruptedIOException (operação de entrada ou saída foi interrompida).
Uma exceção contém pelo menos uma string que a descreve, que pode ser obtida pela aplicação do método getMessage, mas pode eventualmente conter outras informações. Outra informação que pode sempre ser obtida de uma exceção é a sequência de métodos no momento da exceção, obtenível a partir do método printStackTrace. Já a exceção InterruptedIOException, do pacote java.io, inclui um atributo público do tipo inteiro, bytesTransferred, para indicar quantos bytes foram transferidos antes da interrupção da operação ocorrer.
Como exceções fazem parte de uma hierarquia de classes, exceções mais genéricas (mais próximas do topo da hierarquia) englobam aquelas que são mais especíﬁcas. Assim, a forma mais genérica de um bloco try-catch é
pois todas as exceções são derivadas de Exception, definida em java.lang. Se dois blocos catch especiﬁcam exceções em um mesmo ramo da hierarquia, a especiﬁcação do tratamento da exceção derivada deve preceder aquela da mais genérica; caso contrário, a mais específica (derivada) nunca será capturada.

## Erros e exceções de runtime

Exceções consistem de um caso particular de um objeto da classe Throwable, definida em java.lang. Apenas objetos dessa classe ou de suas classes derivadas podem ser gerados, propagados e capturados através do mecanismo de tratamento de exceções. Além de Exception, outra classe derivada de Throwable é a classe Error, que é a raiz das classes que indicam situações que a aplicação não tem como ou não deve tentar tratar. Usualmente indica situações anormais, que não deveriam ocorrer.
Entre os erros deﬁnidos em Java, no pacote java.lang, estão StackOverflowError e OutOfMemoryError. São situações onde não é possível uma correção a partir de um tratamento realizado pelo próprio programa que está executando.
Há também exceções que não precisam ser explicitamente capturadas e tratadas. São aquelas derivadas de RuntimeException, uma classe derivada diretamente de Exception. São exceções que podem ser geradas durante a operação normal de uma aplicação para as quais o compilador Java não irá exigir que o programador proceda a algum tratamento ou que propague a exceção. Entre essas incluem-se ArithmeticException, IllegalArgumentException, IndexOutOfBoundsException e NullPointerException.

## Propagação de exceções

Embora toda exceção que não seja derivada de RuntimeException deva ser tratada, nem sempre é possível tratar uma exceção no mesmo escopo do método cuja invocação gerou a exceção. Nessas situações, é possível propagar a exceção para um nível acima na pilha de invocações. Para tanto, o método que está deixando de capturar e tratar a exceção faz uso da cláusula throws na sua declaração:
Nesse caso, métodoQueNãoTrataExceção reconhece que em seu corpo há a possibilidade de haver a geração de uma exceção, mas não se preocupa em realizar o tratamento dessa exceção em seu escopo. Ao contrário, ele repassa essa responsabilidade para o método anterior na pilha de chamadas. Eventualmente, também o outro método pode repassar a exceção adiante. Porém, pelo menos no método main as exceções deverão ser tratadas ou o programa pode ter sua interpretação interrompida.

## Definição e geração de exceções

Exceções são classes. Assim, é possível que uma aplicação deﬁna suas próprias exceções por meio do mecanismo de deﬁnição de classes. Por exemplo, considere que fosse importante para uma aplicação diferenciar a condição de divisão por zero de outras condições de exceções aritméticas. Neste caso, uma classe DivideByZeroException poderia ser criada:
Neste caso, o argumento para o construtor da superclasse especiﬁca a mensagem que seria impressa quando o método getMessage fosse invocado para essa exceção. Essa é a mesma mensagem que é apresentada para um RuntimeException que não é capturado e tratado.
Para gerar uma condição de exceção durante a execução de um método, um objeto dessa classe deve ser criado e, pelo comando throw, propagado para os métodos anteriores na pilha de execução:
O mesmo comando throw pode ser utilizado para repassar uma exceção após sua captura — por exemplo, após um tratamento parcial da condição de exceção:
Nesse caso, a informação associada à exceção (como o seu ponto de origem, registrado internamente no atributo do objeto que contém a pilha de invocações) é preservada. Caso fosse desejado mudar essa informação, uma nova exceção poderia ser gerada ou, caso a exceção seja a mesma, o método fillInStackTrace poderia ser utilizado, como em