Um recurso muito importante em Java é o uso correto das exceções, saber como tratá-las, para que cada uma serve e onde utilizá-las adequadamente. Neste artigo nós explicaremos sobre sete exceções diferentes em Java, dando exemplos e conceitos didáticos e de fácil entendimento, são elas: ArithmeticException, ArrayIndexOutOfBoundsException, ClassNotFoundException, IOException, IllegalArgumentException, InterruptedException, NullPointerException.

ArithmeticException

Este tipo de exceção ocorre quando alguma operação aritmética é inválida e a mesma gera uma exceção, operações essas que não podem ser resolvidas, como é o caso da divisão por zero.

A ArithmeticException é uma unchecked exception, pelo fato de não precisar ser explicitamente tratada em tempo de design. Não entraremos no mérito do que seja uma exceção checked e unchecked, isso porque não é foco do nosso artigo. Vamos ver alguns exemplos de como pode ocorrer essa exceção. Analise a Listagem 1.

Listagem 1. Simulando uma ArithmeticException


   
  public class SimulandoExcecao {
   
         /**
          * @param args
          */
         public static void main(String[] args) {
               
               /*
                * No código abaixo a exceção irá ocorrer 
                 * pelo fato de dividirmos um número
                * por zero.
                * */  
               int valor1 = 10;
               int valor2 = 0;
               System.out.println(valor1/valor2);
               
               /*
                * Você também pode optar por lançar uma 
                 * exceção por conta própria.
                * Veja um exemplo abaixo
                * */
               
               if (valor1  > valor2){
                 throw new ArithmeticException
                 ("O valor 1 não pode ser maior que o valor 2");
               }
               
         }
   
  }

No exemplo da Listagem 1 você pode notar dois exemplos básicos, um onde basicamente não sabemos que a divisão será feita por zero, imagine por exemplo que você já recebeu os parâmetros valor1 e valor2 de outro local, então inesperadamente o valor2 é igual a zero e a exceção ocorre. No outro exemplo forçamos o lançamento de uma exceção por conta de não condizer com nossa condição.

ArrayIndexOutOfBoundsException

Esta exceção é do tipo “unchecked” e ocorre sempre que você tenta especificar um index inválido do seu array, os index's inválidos são: valor negativo, valor maior que o tamanho da sua lista ou valor igual ao tamanho da sua lista, isso porque sempre começamos contando do zero, então o último elemento é sempre o tamanho da sua lista menos 1. Veja na Listagem 2 como podemos simular uma exceção ArrayIndexOutOfBoundsException.

Listagem 2. Simulando uma ArrayIndexOutOfBoundsException


  import java.util.ArrayList;
  import java.util.List;
   
  public class SimulandoExcecao {
   
         /**
          * @param args
          */
         public static void main(String[] args) {
   
               /*
                * Primeiro definimos nosso arrayList com 5 posições
                */
               List<String> meuArray = new ArrayList<String>();
               meuArray.add("Valor 001");
               meuArray.add("Valor 002");
               meuArray.add("Valor 003");
               meuArray.add("Valor 004");
               meuArray.add("Valor 005");
   
               // Vamos tentar acessar a posição -1 do 'meuArray'.
               meuArray.get(-1);
   
               // Saída:
               /*
                  Exception in thread "main"
                   java.lang.ArrayIndexOutOfBoundsException:
                  -1 at java.util.ArrayList.get(ArrayList.java:324) at
                  SimulandoExcecao.main(SimulandoExcecao.java:25)
                */
   
               /*
                * Vamos tentar acessar a posição 6 do 'meuArray'.
                * Lembrando que o seu
                * tamanho é 5, então consequentemente ele vai de 0 até 4
                */
               meuArray.get(6);
               
               //Saída:
               /*
                *  Exception in thread "main" 
                 * java.lang.IndexOutOfBoundsException: Index: 6, Size: 5
                      at java.util.ArrayList.RangeCheck(ArrayList.java:547)
                      at java.util.ArrayList.get(ArrayList.java:322)
                      at SimulandoExcecao.main(SimulandoExcecao.java:35)
   
                * */
               
               /*
                * Vamos tentar acessar a posição 5 do 'meuArray', 
                 * lembre-se ele só tem até a posição 4.
                * */
               meuArray.get(5);
               
               //Saída:
               /*
                *  Exception in thread "main" 
                 * java.lang.IndexOutOfBoundsException: Index: 5, Size: 5
                      at java.util.ArrayList.RangeCheck(ArrayList.java:547)
                      at java.util.ArrayList.get(ArrayList.java:322)
                      at SimulandoExcecao.main(SimulandoExcecao.java:49)
                * */
   
         }
   
  }

A própria exceção já lhe diz exatamente qual o problema, por exemplo no caso onde colocamos o 6 ele disse: O tamanho da lista é 5 e o index pedido é 6.

ClassNotFoundException

Este tipo de exceção é checked e como o próprio nome já sugere, ela ocorre quando alguma classe não é encontrada no seu classpath. Porém como sabemos, se tentarmos importar uma classe em tempo de design (design-time) e ela não existir, simplesmente a sua IDE mostrará um erro e você nem conseguirá executar o programa, mas para outros casos como o carregamento de classes via String, o ClassNotFoundException pode ocorrer.

Existem então três métodos básicos onde ele pode ocorrer:

  1. forName da classe Class;
  2. findSystemClass da classe ClassLoader;
  3. loadClass da classe ClassLoader;

O principio é o mesmo, tentar carregar uma classe usando uma String, ou seja, carregar a classe em tempo de execução (run-time). Vamos ver um exemplo simples na Listagem 3.

Listagem 3. Simulando ClassNotFoundException


   
  public class SimulandoExcecao {
   
         /**
          * @param args
          */
         public static void main(String[] args) {
   
               try {
                      Object o = Class.forName("pacote.NaoExiste")
                      .newInstance();
               
                      System.out.println("Essa linha nunca será chamada");
                      
               } catch (ClassNotFoundException e) {
                      System.err.println("A classe pacote.NaoExiste não 
                      existe mesmo !");
                      e.printStackTrace();
               } catch (InstantiationException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
               } catch (IllegalAccessException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
               }
   
         }
   
  }

Perceba que o “Class.forName()” ainda exige o tratamento de outras exceções, mas não são o foco deste artigo.

IOException

Essa exception ocorre quando algum sinal de entrada/saída falha ou é interrompido, por exemplo uma leitura de um arquivo em disco, caracteriza-se também por ser um checked exception. Esta é a mais genérica classe para erros de Entradas e Saídas (Input/Output), mas existem classes mais específicas como: FileNotFoundException, SocketException, SSLException e assim por diante.

Na Listagem 4 vamos ver um exemplo de tentativa de leitura em um arquivo inexistente, obviamente que ocorrerá uma IOException pela falha na leitura em disco.

Listagem 4. Simulando IOException


  import java.io.BufferedReader;
  import java.io.FileReader;
  import java.io.IOException;
   
  public class SimulandoExcecao {
   
         /**
          * @param args
          */
         public static void main(String[] args) {
   
               BufferedReader br = null;
   
               try {
                      br = new BufferedReader(new FileReader
                       ("/tmp/arquivoInexistente"));
               } catch (IOException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
               }
   
         }
   
  }

Perceba que tentamos realizar a leitura de um arquivo que não existe em disco, isso nos causará um “FileNotFoundException”, mas podemos generalizar usando o “IOException”.

IllegalArgumentException

Este tipo exceção geralmente é utilizada para validar valores de parâmetros que não estão nas condições adequadas ao programa, ou seja, você pode querer que um parâmetro do seu método que é do tipo inteiro, nunca seja maior que 100 para evitar falhas no sistema, para isso você pode fazer uso do IllegalArgumentException, veja um exemplo na Listagem 5.

Listagem 5. Simulando IllegalArgumentException


  public class SimulandoExcecao {
   
         /**
          * @param args
          */
         public static void main(String[] args) {
               
               meuMetodoTeste(101);
   
         }
         
         public static void meuMetodoTeste(int param1){
               if (param1 > 100){
                      throw new IllegalArgumentException
                        ("O param1 não pode ser maior que 100, 
                         viola a integridade da aplicação");
               }
         }
   
  }

Vale lembrar que a IllegalArgumentException é um unchecked exception.

InterruptedException

Esta exceção é lançada quando uma Thread está aguardando, dormindo ou pausada e uma outra Thread a interrompe. Veja o exemplo na Listagem 6.

Listagem 6. Simulando InterruptedException


  public class SimulandoExcecao extends Thread {
   
         public void run() {
               for (int i = 0; i < 10; i++) {
                      try {
                             Thread.sleep(1000);
                      } catch (InterruptedException e) {
                             System.err.println("Sleep is disturbed. " + e);
                      }
   
                      System.out.println("Iteration: " + i);
               }
         }
   
         public static void main(String args[]) {
               SimulandoExcecao d1 = new SimulandoExcecao();
               d1.start();
               try {
                      d1.join();
               } catch (InterruptedException e) {
                      System.err.println("Properly not 
                       joined with parent thread. " + e);
               }
         }
  }

Esta é uma checked exception, que precisa obrigatoriamente estar em um bloco try/catch ou ser “lançada” através de um throws.

NullPointerException

Podemos dizer que está é uma das mais conhecidas exceções, que ocorre com maior frequência. Ela ocorre quando há uma tentativa de acessar algum objeto que seja “null”, Exemplo: Quando você tentar chamar o método “size()” de um ArrayList que ainda não foi instanciado.

Com este artigo você pode ter uma visão geral de algumas entre as muitas exceções que existem na linguagem Java, estas são apenas algumas que ocorrem com muita frequência e podem de fato tornar-se uma dor de cabeça para o desenvolvedor.