Exceção em Java

Exceções são um tipo de erro que para de executar o programa ao encontrar uma, isso ocorre devido a um erro do programador,  uma entrada de dados não valida ou algum erro de comunicação com um servidor por exemplo.
Quando tratadas, o programa não interrompe sua execução ao achar.

Há 2 tipos de exceções:


1. CHECADAS (Classe Exception):
-São checadas em tempo de compilação, permitindo o tratamento no momento que ocorre a exceção ou vai propagando para algum, momento tratá-la, com isso não há interrupção da execução do programa (Exemplos: IOException, SQLException)
-É obrigatório o tratamento, seja capturando ou propagando.
-Deve-se tratar utilizando TRY-CATCH ou declará-la utilizando a palavra throws;
-Geralmente são condições invalidas, fora do controle do programa, entrada de dados do usuário, acesso a um banco de dados, rede, entre outros motivos.


2. NÃO CHECADAS (Classe Runtime):
-São exceções que são checadas em tempo de execução, ocorrendo a interrupção do programa (Exemplos: ArrayOutOfBoundsException,  ArithmeticException, ArrayIndexOfBoundsException, NullPointerException, ClassCastException)
-O tratamento das exceções é opcional;
-Tipicamente relacionadas com defeitos (bugs) de programação, quebra de pré-condições, invariantes, entre outros motivos.
os ERROR em Java, não conseguimos tratar, pois não temos cobntrole sobre eles, logo não temos o que fazer. Um exemplo de ERROR é o StackOverFlow.
Quando o erro for no código, deve-se abortar o programa e não criar uma exceção.

Quando é criada uma exceção que não é disparada, ou seja, não aconteceu, ela automaticamente abortará o programa;

Uso do throw no meio do código serve para disparar a exceção;
Uso do throws no começo da exceção serve para dizer que pode ou não disparar;

PORQUE NÃO DEVEMOS UTILIZAR A EXCEÇÃO RunTimeException PARA CAPTURAR EXCEÇÕES?

Pois ela é muito genérica. Com isso, deve-se sempre utilizar a exceção mais específica a ser tratada;


BLOCO TRY-CATCH:

Try:
-Traduzindo para portugueses significa "tente".
-Nesse bloco possui o código que possivelmente dará algum erro, seja por erro do programador (não deveria) ou até mesmo por erro do usuário.

Catch:
-Bloco de tratamento da exceção;
-Geralmente captura-se a exceção e, devolve uma mensagem informando case entre nesse bloco, assim, informando ao usuário sobre a exceção;
-Deve-se explicitar a exceção esperada a ser capturada;
-Após executar o catch, o programa continuará com a próxima instrução após o catch, pois a exceção já foi tratada;
-Uso:
}catch(TipoExcecao objExcecao){
       //tratamento da exceção
}



Exemplo:

class  public Excecao {
public  static  void  main ( String [] args ) {

try {
          int [] vetor =  novo  int [ 4 ];
System.out.println( " Antes da exceção " );
vetor [ 4 ] =  1 ;  //vai dar erro pois, na posição 4 não existe, já que array começa do índice 0 (zero)
System.out.println( " Esse texto não seráito " );
} catch ( ArrayIndexOutOfBoundsException e) {
System.out.println( " Exceção ao acessar um índio do vetor que não existe " );
}
System.out.println( "Este texto será calculado após uma excepção " );
 }
}



BLOCO TRY-CATCH-CATCH:

Bloco em que captura-se mais de uma exceção.


Exemplo:

public class MultiplosCatch {
 public static void main(String[] args) {
  int[] numeros = {4, 8, 16, 32, 64, 128};
  int[] demon = {2, 0, 4, 8, 0};
  
  for(int i=0;i<numeros.length ; i++){
          try{
               System.out.println(numeros[i] + "/" + demon[i] + "= " + (numeros[i]/demon[i])); //aqui pode dar divisão por 0, assim dará uma exceção.
        }catch(ArithmeticException e1){
              System.out.println("Erro ao dividir por 0 (zero) ! ");
        }catch(ArrayIndexOutOfBoundsException e2){
              System.out.println("Erro ao dividir por 0 (zero) ! ");  //aqui poderá dar um erro de que o array numeros tem mais elementos de o demon, sendo assim o ultimo elemento do array numeros não dividirá por nenhum demon, mostrando que há exceção
        }
  } 
 }
}

Exemplo de como capturar 2 exceções dentro do mesmo CATCH pertencem a mesma superclasse:
Isso é possível após o java 7.

public class MultiplosCatchJava {

public static void main(String[] args) {

int[] numeros = {4, 8, 16, 32, 64, 128};
int[] demon = {2, 0, 4, 8, 0};

for(int i=0;i<numeros.length ; i++){
try{
System.out.println(numeros[i] + "/" + demon[i] + " = " + (numeros[i]/demon[i]));
}catch(ArithmeticException | ArrayIndexOutOfBoundsException  e){
System.out.println("Aconteceu um erro");
}
}
}
}

QUAL É UMA ALTERNATIVA AO TRY-CATCH?

O throws.


BLOCO TRY-FINALLY:

Se não der uma exceção no bloco TRY, o FINALLY é sempre executado.
Logo se ocorrer uma exceção no meio do TRY, ele para de executar e executa o FINALLY.


BLOCO TRY-CATCH-FINALLY:

O bloco finally é sempre executado após o bloco TRY-CATCH.
É muito utilizado para:
   -Abrir arquivo;
   -Realizar leitura;
   -Quando ocorre um erro;
   -Fechar um arquivo no finally;

Exemplo:

public class TryCatchFinally {

public static void main(String[] args) {

int[] numeros = {4, 8, 16, 32, 64, 128};
int[] demon = {2, 0, 4, 8, 0};

for(int i=0;i<numeros.length ; i++){
         try{
System.out.println(numeros[i] + "/" + demon[i] + " = " + (numeros[i]/demon[i]));
}catch(ArithmeticException | ArrayIndexOutOfBoundsException  e){
System.out.println("Aconteceu um erro");
}finally{
               System.out.println("O finally sempre será executado");
}
}
}

MAS E SE NÃO SOUBERMOS A FUTURA EXCEÇÃO QUE OCORRERÁ? COMO FICA?

Podemos capturar exceções genéricas através da superclasse de todas as exceções chamada "Throwable", utilizando dentro do catch.
Lembre-se: quando for usar múltiplos CATCHS's use primeiro a exceção mais especifica e após a mais genérica, que no caso seria a "Throwble".

PARA O CÓDIGO FICAR MAIS LIMPO E ELEGANTE, prefira o Exception a Throwble.


CLASSE throwable

-Classe mãe de todas as exceptions, ou seja, todas as exceções herdam de throwable;
-Possui métodos úteis;
-O método getMessage() :  retorna a descrição do erro;
-O método printStackTrace() : imprime o stack trace do erro, ou seja, a linha e classe que ocorreu a exceção;
Caso seja um sistema de grande escala, nunca informe o stack trace ao usuário e sim, grave em um arquivo de log para poder ficar mais fácil de procurar onde aconteceu o erro.Sendo assim, deve mostrar ao usuário uma mensagem mais amigável, assim não informa a linguagem que está sendo utilizada (no erro deixa explicito) e onde ocorreu o erro (linha e classe) , com isso não deixa o sistema vulnerável a ataques.


Exemplo:

public class ExceptionGenerica {

 public static void main(String[] args) {

int[] numeros = {4, 8, 16, 32, 64, 128};
int[] demon = {2, 0, 4, 8, 0};

for (int i=0; i<numeros.length; i++){
try{
System.out.println(numeros[i] + "/" + demon[i] + " = " + (numeros[i]/demon[i]));
}
catch(Exception e){
System.out.println(e.getMessage());
e.printStackTrace(); //aqui mostrará a linha e classe que houve a exceção sem interromper a execução do programa, permitindo guardar em um log
}
}

 }
}

PALAVRA CHAVE throws:

-Método para disparar uma Exception;
-Usado para postergar o tratamento da exceção , passando a responsabilidade para quem for utilizar o método;
Exceptions disparadas em tempo de execução (ArrayOutOfBoundsException, ArithmeticException) não necessitam de throws explicitamente;
Uso do throws no começo da exceção serve para dizer que pode ou não disparar;

Exemplo:

import java.util.Scanner;

public class UsandoThrows {

public static void main(String[] args) {

System.out.println("Entre com um número decimal");
try {
double num = leNumero();
System.out.println("Você digitou " + num);
} catch (Exception e) {
System.out.println("Entrada inválida");
e.printStackTrace();  //retorna a linha e classe que houve a exceção, fazendo que não interrompa a execução do programa
}

}

public static double leNumero() throws Exception {  //quem utilizar esse método terá que tratar, que no caso será tratado no main
Scanner scan = new Scanner(System.in);
double num = scan.nextDouble();
return num;
}
}




CRIANDO A SUA PRÓPRIA EXCEÇÃO:


public class UsandoMinhaException {

public static void main(String[] args) {

try {
teste();
} catch (DivisaoNaoExata e) {
e.printStackTrace();
}
}

public static void teste() throws DivisaoNaoExata{
int[] numeros = {4, 8, 5, 16, 32, 21, 64, 128};
int[] demon   = {2, 0, 4, 8,  0,  2,  4};

for (int i=0; i
try{
if (numeros[i] % 2 != 0){ //verifica se a divisao vai ter um resultado decimal
//lançar a exception aqui
throw new DivisaoNaoExata(numeros[i], demon[i]);
}
System.out.println(numeros[i] + "/" + demon[i] + " = " + (numeros[i]/demon[i]));
}
catch(ArithmeticException | ArrayIndexOutOfBoundsException e){
System.out.println("Aconteceu um erro");
e.printStackTrace();
}
}
}

}

public class DivisaoNaoExata extends Exception {

private int num;
private int dem;

public DivisaoNaoExata(int num, int dem) {
super();
this.num = num;
this.dem = dem;
}

@Override
public String toString() {
return "Resultado de " + num + "/" + dem + " não é um inteiro!";
}

}

Comentários

Postagens mais visitadas deste blog

Método da Interpolação por Eliminação Gaussiana em Scilab

Cálculo do Erro para Interpolação em Scilab

Método de Interpolação de Lagrange em Scilab