Exceptions
Exceptions
Considerando o que foi visto em Pilha de execução.
Quando um exceção (situação excepcional) ocorre, o JVM entra em estado de alerta e procura dento do metodo se existe algum tratamento especial para o problema.
class TesteErro {
public static void main(String[] args) {
System.out.println("inicio do main");
metodo1();
System.out.println("fim do main");
}
static void metodo1() {
System.out.println("inicio do metodo1");
metodo2();
System.out.println("fim do metodo1");
}
static void metodo2() {
System.out.println("inicio do metodo2");
int[] array = new int[10];
for (int i = 0; i <= 15; i++) {
array[i] = i;
System.out.println(i);
}
System.out.println("fim do metodo2");
}
}- Como o
metodo2não tem nenhum tratamento a JVM interrompe sua execução e volta um nível na pilha e verifica novamente. - Como o
metodo1também não faz nenhum tratamento a JVM sobe mais um nivel até chegar nomain - Como o
maintambém não faz nenhum tratamento a Thread morre.
O tratamento de erros em Java é feito em tempo de execução através do tratamento de exceção. As exceções são classes que seguem o modelo OO e são lançadas quando o sistema encontra um problema mas podem ser utilizadas também para validar regras de negócio.
Exception(exceção) significa "condição excepcional", e é uma ocorrência que altera o fluxo normal do programa.
Dicas
Quando um evento excepcional ocorre em java, diz-se que uma exceção será lançada.
- Métodos podem capturar ou deixar passar exceções que ocorrerem em seu corpo, mas para isto é obrigatório que o método declare a sua decisão.
- Para repassar o tratamento de erro para quem chama o método utilizamos o
throws.throwsdeclara que o método pode provocar exceções do tipo declarado (ou de qualquer subtipo).
public void validar() throws Excecao1, Excecao2 {…}Para tratar a exceção no método utilizamos o try/catch.
try {
for (int i = 0; i <= 15; i++) {
array[i] = i;
IO.println(i);
}
} catch (ArrayIndexOutOfBoundsException e) {
IO.println("erro: " + e);
}Executando o código novamente
erro: java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 10
fim do metodo2
fim do metodo1
fim do main?
- Modificando o try para dentro do for qual será o comportamento?
- E na chamada do metodo2?
- E na chamada do metodo1?
- Divisão por 0
- Referência Nula
A partir do momento que uma exception foi catched (pega, tratada, capturada , handled), a execução volta ao normal a partir daquele ponto.
ArrayIndexOutOfBoundsException ou um NullPointerException poderia ser facilmente evitado com o for corretamente escrito ou com ifs que checariam os limites da array. Tais problemas provavelmente poderiam ser evitados pelo programador
Tipos de Exception
- Checadas (Verificadas) –> o compilador verifica e obriga os usuários que chamam o método ou construtor a tratar a exceção
- Não – checadas –> o compilador não verifica, são os subtipos de Error e RuntimeException
Dicas
RuntimeException é a exception mãe de todas as exceptions não checadas
Abrir um arquivo para leitura
public class AbrirArquivo {
public static void metodo() {
new java.io.FileInputStream("arquivo.txt");
}
}O código acima não compila e o compilador avisa que é necessário tratar o FileNotFoundException que pode ocorrer.Para compilar e fazer o programa funcionar, temos duas maneiras que podemos tratar o problema. A primeira é tratá-lo com o try e catch e a segunda forma de tratar esse erro, é delegar ele para quem chamou o nosso método, isto é, passar para a frente.
public static void metodo() {
try {
new java.io.FileInputStream("arquivo.txt");
} catch (java.io.FileNotFoundException e) {
IO.println("Não foi possível encontrar o arquivo para leitura");
}
}public static void metodo() throws java.io.FileNotFoundException {
new java.io.FileInputStream("arquivo.txt");
}É possível fazer o tratamento de mais de uma exceção no mesmo bloco para ambas abordagens
try{
//Codigo verificado
}catch(TipoExcecao1 ex1){
//Captura uma exceção TipoExcecao1
}catch(TipoExcecao2 ex2){
//Captura uma exceção TipoExcecao2
}public void metodo() throws TipoExcecao1, TipoExcecao2 {
//…
}package exceptions.connection;
import java.sql.Connection;
import java.sql.SQLException;
public class DAO {
Connection connection;
public DAO() {
this.connection = new ConnectionFactory().getConnection();
}
public void save(String sql) {
try {
this.connection.prepareStatement(sql).execute();
connection.close();
} catch (SQLException e) {
// mandar mensagem para equipe de desenvolvimento
e.printStackTrace();
}
catch (Exception e) {
// mandar mensagem para equipe de infra
e.printStackTrace();
}
}
}Não há uma regra para decidir em que momento do seu programa deve ser feito o tratamento da exceção. Essa decisão depende de como a exceção será tratada e em que ponto é possível fazer algo a respeito. Enquanto não for o momento, provavelmente será melhor delegar a responsabilidade para o método que invocou. Lembrando que: caso o tratamento não seja feito por nenhum código quem irá tratar é a JVM.
try {
for(int i = 0; i <= 15; i++) {
array[i] = i;
IO.println(i);
}
} catch (ArrayIndexOutOfBoundsException e) {
IO.println("erro: " + e);
}for(int i = 0; i <= 15; i++) {
try {
array[i] = i;
IO.println(i);
} catch (ArrayIndexOutOfBoundsException e) {
IO.println("erro: " + e);
}
}Para lançar a Exceção explicitamente utilizamos o throw e criamos uma instancia da classe que representa a exceção desejada
public class MinhaException extends Exception {
}
...{
public double dividir(double v1, double v2) throws MinhaException {
if(v2==0){
throw new MinhaException("Divisão por ZERO");
}
}
}Finally
Os blocos try e catch podem conter uma terceira cláusula chamada finally que indica o que deve ser feito após o término do bloco try ou de um catch.
try {
// bloco try
} catch (IOException ex) {
// bloco catch 1
} catch (SQLException sqlex) {
// bloco catch2
} finally {
// bloco finally
}É interessante colocar algo que é imprescindível de ser executado, caso o que você queria fazer tenha dado certo, ou não. O caso mais comum é o de liberar um recurso no finally, como um arquivo ou conexão com banco de dados, para que possamos ter a certeza de que aquele arquivo (ou conexão) vá ser fechado, mesmo que algo tenha falhado no decorrer do código.
O bloco finally sempre será executado, salvo em raras situações.
De forma geral ele é a garantia de que seu código irá liberar recursos ocupados mesmo que ocorram exceções (Exceptions) ou o método contendo o try retorne prematuramente (return).
Dicas
Os únicos momentos em que o finally não será chamado são:
- Se você chamar System.exit() ou
- um outro thread interromper o atual (através do método interrupt()) ou
- Se a JVM der crash antes.
- O bloco
trydeve ser precedido por umcatchoufinalliy - O
finallyquer dizer que dando erro ou não o trecho de código compreendido nele será executado - O
catchserá executa somente se naquele trecho dentro do try resultar em algum erro
Dicas
RuntimeException é a exception mãe de todas as exceptions não verificadas
Dicas
IllegalArgumentException é uma exceção do pacote do java que podemos utilizar para tratar valores indevidos para chamadas de métodos