Exceções (Exception) [RESOLVIDO]

33 respostas
ECO2004

[b]Olá pessoal!

Precisaria de uma dúvida com uma Exception.

Gostaria de saber porque a minha classe diz que a exceção não foi tratada (na main).[/b]

public class Main 
{
    public static int f(int x, int y) throws ArithmeticException 
    {
        try 
        {
             System.out.println(" 1 ");
             return x/y;
        }

       catch(ArithmeticException ex) 
      {
            System.out.println(" 2 ");
            throw ex;
      }

      finally 
     {
            System.out.println(" 3 ");
     }
  }

    public static int g(int x, int y) throws Exception 
    {
        try 
        {
             System.out.println(" 4 ");
             return x/y;
        }

       catch(ArithmeticException ex)
       {
           System.out.println(" 5 ");
           throw ex;
       }

       finally 
      {
          System.out.println(" 6 ");
      }
  }

  public static void main(String[] args) 
  {
          g(10, 0);
  }
}

Se eu tiro throws Exception, não é mais dito que a exceção não foi tratada. Se eu tiro ArithmeticException do catch e troco por Exception, o mesmo errp persiste. Por quê?
Por acaso é proibido ter um throw Exception e embaixo, o seu tratamento?

33 Respostas

Rodrigo_Sasaki

se você deixa o throws, isso diz para o método que invoca ele, que essa exceção tem que ser tratada…

se você trata ela (try/catch) dentro do método, não precisa ter o throws na assinatura, porque não precisa tratar 2x hehe

ou você trata ela com um bloco try/catch, ou adiciona o throws na assinatura, fazendo com que o método(no seu caso o main) que invoca esse método(no seu caso o f) tenha que tratá-lo.

drsmachado

Primeiro entenda o que é o throws. Ele dispensa o uso do try/catch. Ele vai jogar a responsabilidade de tratar o erro para a classe/método que o chamou.
Por isso, ao tirar o throws ArithmeticException e mantendo o try/catch roda normalmente.
Se vai usar o throws, tire todos os blocos try/catch referentes à mesma exception se, vai usar try/catch, tire o throws correspondente…

ECO2004
drsmachado:
Primeiro entenda o que é o throws. Ele dispensa o uso do try/catch. Ele vai jogar a responsabilidade de tratar o erro para a classe/método que o chamou. Por isso, ao tirar o throws ArithmeticException e mantendo o try/catch roda normalmente. Se vai usar o throws, tire todos os blocos try/catch referentes à mesma exception se, vai usar try/catch, tire o throws correspondente..

Isso que você disse não é uma regra. É boa programação. Tanto é que a primeira função do código funciona normalmente (caso eu troque g por f, com os mesmos parâmetros).

public static int f(int x, int y) throws ArithmeticException   
    {   
        try   
        {   
             System.out.println(" 1 ");   
             return x/y;   
        }   
  
       catch(ArithmeticException ex)   
      {   
            System.out.println(" 2 ");   
            throw ex;   
      }   
  
      finally   
     {   
            System.out.println(" 3 ");   
     }   
  }

O trecho acima funciona perfeito, com f(10, 0).

ECO2004

digaoneves:
se você deixa o throws, isso diz para o método que invoca ele, que essa exceção tem que ser tratada…

se você trata ela (try/catch) dentro do método, não precisa ter o throws na assinatura, porque não precisa tratar 2x hehe

ou você trata ela com um bloco try/catch, ou adiciona o throws na assinatura, fazendo com que o método(no seu caso o main) que invoca esse método(no seu caso o f) tenha que tratá-lo.

O throws somente diz que uma exceção pode acontecer. A obrigatoriedade de tratar, seja por catch ou por declare, é um requisito somente de exceções verificadas, como uma IOException. Se eu não tratar, será gerado uma mensagem padrão na pilha.

Rodrigo_Sasaki

e por acaso o bloco catch é executado todas as vezes?

pra mim é a mesma coisa, uma possível exceção tratadas em situações (chamadas) diferentes.

agora ter os 2 obriga você a tratar o mesmo duas vezes não concorda? uma vez dentro do método em si, e outra vez no método que o invoca

drsmachado

Determinados métodos obrigam você a indicar que, ou a classe que está invocando-o irá tratar possível erro ou que aquele trecho seja circundado com try/catch (tente instanciar uma classe por reflection, usando o Class.forName(“String”); e veja o que acontece se não colocar um dos dois).

Se vocë teve o mínimo interesse em ver qual o motivo pelo qual a IDE acusa erro quando usa a chamada ao método g, teria percebido que ele trata de uma menção ao throws Exception, cuja chamada não é tratada.

Enfim, isto fica a teu critério, camarada.

ECO2004

digaoneves:
e por acaso o bloco catch é executado todas as vezes?

pra mim é a mesma coisa, uma possível exceção tratadas em situações (chamadas) diferentes.

agora ter os 2 obriga você a tratar o mesmo duas vezes não concorda? uma vez dentro do método em si, e outra vez no método que o invoca

Bem, olha o que entendi…

O throws indica que poderá ser lançado uma exceção. Como Exception é uma exceção verificada, exige que eu a trate. Eu posso tratar dentro do método g() ou na chamada de g(), na main. No último caso, colocaria a chamada em try/catch e pronto. Porém, eu quero tratar dentro do método. Se eu colocar mais um catch, com Exception, ainda diz que eu não tratei a exceção.

Estou achando que não pode usar throws Exception no método se você pretende tratá-la nela.

É isso?

Rodrigo_Sasaki

É isso que a gente ta tentando explicar
se você vai tratar dentro do método, só apague o throws…

ECO2004

digaoneves:
É isso que a gente ta tentando explicar
se você vai tratar dentro do método, só apague o throws…

Mas porque somente dá erro com o throws Exception e com as demais não dá? Tem throws ArithmeticException e tratada dentro do método.
O método f() funciona perfeitamente (trocando g() por f() na main).

ECO2004

.

drsmachado

ECO2004:

Mas porque somente dá erro com o throws Exception e com as demais não dá? Tem throws ArithmeticException e tratada dentro do método.
O método f() funciona perfeitamente (trocando g() por f() na main).

Espertão, troca o catch(ArithmeticException ex) do método g por catch(Exception ex) e testa.
Você está dizendo que, independente do código, você poderá lançar uma exception. Porém, em nenhum lugar há um tratamento para esta exception.

Pense no seguinte, se você tem um método que pode retornar null ou uma String e só trata a String e não o null, em algum momento pode ter um NullPointerException, certo?

ECO2004

drsmachado:
ECO2004:

Mas porque somente dá erro com o throws Exception e com as demais não dá? Tem throws ArithmeticException e tratada dentro do método.
O método f() funciona perfeitamente (trocando g() por f() na main).

Espertão, troca o catch(ArithmeticException ex) do método g por catch(Exception ex) e testa.
Você está dizendo que, independente do código, você poderá lançar uma exception. Porém, em nenhum lugar há um tratamento para esta exception.

Pense no seguinte, se você tem um método que pode retornar null ou uma String e só trata a String e não o null, em algum momento pode ter um NullPointerException, certo?

Há um tratamento. O tratamento está no bloco catch(Exception ex).

public static int f(int x, int y) throws Exception
	{
		 try 
		 {
			 System.out.println(" 1 ");
			 return x/y;
		 }
		 
		 
		 catch(Exception ex)
		 {
			 return -1;
		 }
		 
		 finally 
		 {
			 System.out.println(" 3 ");
		 }
	}
drsmachado

E você leu a parte do “do método g por”, certo?

Sugiro fazer o seguinte:

1 - Refaça a classe toda, sem qualquer tratamento de exception.

2 - Inclua apenas try/catch(Exception e)

3 - Retire todos os try/catch e coloque apenas throws Exception

4 - Não altere o modelo anterior. Coloque try/catch(Exception e) na chamada ao método em questão (ou ambos)

5 - Desfaça tudo e coloque try/catch(ArithmeticException ae) nos métodos

6 - Troque o try/catch por throws ArithmeticException sem tratamento em qualquer lugar

7 - Trate com try/catch na chamada dos metodos

Se mesmo assim continuar a não entender, me desculpe, mas programar não é para você. Pare enquanto é tempo e vá ser político.

dieguittom

No caso do bloco

catch(Exception ex)

irá executar em todas as exceções
você pode ter varios blocos catch para executar coisas específicas para cada tipo de exceção partindo da menos genérica pra a mais genérica ex.

try {
	//codigo
			
	} catch (NullPointerException ex) {
		// Codigo
	} catch (Exception ex) {
		// Codigo
	}
drsmachado

dieguittom, você pode ter, também, vários throws

thros ArithmeticException, NullPointerException, NoSuchMethodException, Exception

A questão é…
Em algum momento, estas coisas precisam ser tratadas.

dieguittom

Correto
e como você já disse:
ou usa try/catch para tratar ou usa throws para jogar a responsabilidade de tratar o erro para a classe/método que o chamou.

drsmachado

dieguittom:
Correto
e como você disse
ou usa try/catch para tratar ou usa throws para jogar a responsabilidade de tratar o erro para a classe/método que o chamou.

Se lançar com throws, tem que tratar o erro na chamada.

discorpio

Bom dia a todos.

O que voce precisa entender é que quando voce lança a exceção com throws Exception para que outro método invocador, ela tem que ser tratada de qualquer forma no método invocador, e no seu caso, voce tem que definir um try…catch dentro do método starter public void main(…), se voce não fizer o tratamento ali, vai dar erro e é isso que o pessoal está tentando te explicar. Execute o código abaixo e vê o que acontece.

public class Main   
{  
    public static int f(int x, int y) throws Exception   
    {  
        try   
        {  
             System.out.println(" 1 ");  
             return x/y;  
        }  
  
       catch(ArithmeticException ex)   
      {  
            System.out.println(" 2 ");  
            throw ex;  
      }  
  
      finally   
     {  
            System.out.println(" 3 ");  
     }  
  }  
  
    public static int g(int x, int y) throws Exception   
    {  
        try   
        {  
             System.out.println(" 4 ");  
             return x/y;  
        }  
  
       catch(ArithmeticException ex)  
       {  
           System.out.println(" 5 ");  
           throw ex;  
       }  
  
       finally   
      {  
          System.out.println(" 6 ");  
      }  
  }  
  
  public static void main(String[] args)   
  { 
        try { 
             f(10, 0);
        } catch (Exception ex) {
             System.out.println(ex.getMessage());
        }
  }  
}

Repare que mesmo que a exceção ArithmeticException seja tratata no método inicial, o disparo da exceção tratada no método starter main só será efetuado se houver qualquer outra exceção que não seja ArithmeticException, contudo, isto não constitui uma boa prática de programação. Se voce pretende tratar todas as exceções e não sabe o nome de todas elas, use a classe Exception que é mãe de todas as classes de Exceção, ou seja, todas as exceções herdam (extendem) de Exception, assim o seu código ficaria limpo desta forma:

public class Main   
{  
    public static int f(int x, int y)  
    {  
        try   
        {  
             System.out.println(" 1 ");  
             return x/y;  
        }  
  
       catch(Exception ex)   
      {  
            System.out.println(" 2 \n" + ex.getMessage()");
               
      }  
  
      finally   
     {  
            System.out.println(" 3 ");  
     }  
  }  
   
  
  public static void main(String[] args)   
  { 
        f(10,0);
  }  
}

// ou assim:

public class Main   
{  
    public static int f(int x, int y)  throws Exception
    {  
        return x/y;
    }   
  
  public static void main(String[] args)   
  { 
        try { 
             f(10, 0);
        } catch (Exception ex) {
             System.out.println(ex.getMessage);
        }
  }  
}
L

Respondendo à pergunta original…

O compilador requer que você coloque o “throws” no main porque na definição do método você declarou “throws Exception”. Isso indica que aquele método pode arremessar uma exception do tipo Exception. Algumas exceções podem ser arremessadas sem ninguém tratar (todas as derivadas do RuntimeException). A ArithmeticException é uma delas. A Exception não.

Com a linha do “g”, o compilador vê: alguém arremessa uma exceção que deve ser tratada e não é por ninguém. Por isso, ele chia. Com o “f”, ele vê "ah, é uma RuntimeException, ninguém precisa tratar (mas pode tratar se quiser).

Com o “throws” no main, você delega o tratamento para quem chama ela.

Ficou claro?!

ECO2004

leo.andven:
Respondendo à pergunta original…

O compilador requer que você coloque o “throws” no main porque na definição do método você declarou “throws Exception”. Isso indica que aquele método pode arremessar uma exception do tipo Exception. Algumas exceções podem ser arremessadas sem ninguém tratar (todas as derivadas do RuntimeException). A ArithmeticException é uma delas. A Exception não.

Com a linha do “g”, o compilador vê: alguém arremessa uma exceção que deve ser tratada e não é por ninguém. Por isso, ele chia. Com o “f”, ele vê "ah, é uma RuntimeException, ninguém precisa tratar (mas pode tratar se quiser).

Com o “throws” no main, você delega o tratamento para quem chama ela.[/quote=leo.andven]

Ficou claro?!

Primeiramente, obrigado pela explicação…

public static int g(int x, int y) throws Exception     
    {     
        try     
        {     
             System.out.println(" 4 ");     
             return x/y;     
        }     
     
       catch(Exception ex)     
       {     
           System.out.println(" 5 ");     
           throw ex;     
       }     
     
       finally     
       {     
          System.out.println(" 6 ");     
       }     
  }  

public static void main(String[] args)     
{ 
      g(10, 0);   
}

1 - A main chama o método “g”.
2 - O método “g” pode lançar uma exceção do tipo Exception.
3 - Exception é uma exceção verificada. Precisa ser tratada.
4 - Exception é tratada no próprio método. Há um catch(Exception ex).
5 - Mesmo assim, há erro dizendo que não tratei a exceção.

O pessoal tá bravo porque estou insistindo no assunto. Parece que não entendo. Mas não entendo porque o pessoal tá falando que throws é usado quando não é responsabilidade do método implementar a captura da exeção. É boa prática de programação, não regra.

1 - Se tem throws, ela joga a responsabilidade para quem chamou o método.
2 - Caso contrário, trate com try/catch - se quiser, pois depende se é obrigatório ou não.

Bem, eu sei fazer o programa funcionar.

1 - Retire o throws Exception
ou
2 - try/catch na chamada do método.

Não é o que quero.

Se eu faço:

public static int g(int x, int y) throws ArithmeticException
    {     
        try     
        {     
             System.out.println(" 4 ");     
             return x/y;     
        }     
     
       catch(ArithmeticException ex)     
       {     
           System.out.println(" 5 ");     
           throw ex;     
       }     
     
       finally     
      {     
          System.out.println(" 6 ");     
      }     
  }

Tudo Ok.

Seu eu faço:

public static int g(int x, int y) throws Exception     
    {     
        try     
        {     
             System.out.println(" 4 ");     
             return x/y;     
        }     
     
       catch(Exception ex)     
       {     
           System.out.println(" 5 ");     
           throw ex;     
       }     
     
       finally     
      {     
          System.out.println(" 6 ");     
      }     
  }

…não funciona (pia, como o amigo disse acima). Isso é independente de qual exceção esteja sendo tratada no catch. O problema está no thows Exception.

Na chamada do método “g(10, 0)”, certamente gerará uma ArithmeticException. Porém, ArithmeticException é filha de Exception. Quando o JVM vir a minha função, ele verá que o método pode gerar uma exceção e pedirá para que seja tratado. E é isso que faço quando coloco catch(Exception) em “g”.

Com outras exceções não preciso fazer isso…

public static int g(int x, int y) throws ArithmeticException     
    {     
        try     
        {     
             System.out.println(" 4 ");     
             return x/y;     
        }     
     
       catch(ArithmeticException ex)     
       {     
           System.out.println(" 5 ");     
           throw ex;     
       }     
     
       finally     
      {     
          System.out.println(" 6 ");     
      }     
  }

public static void main(String[] args)     
{          
         g(10, 0);   
}

…acima, não preciso.

Se falarem NÃO PODE USAR THROWS EXCEPTION NO MÉTODO EM QUE ESTÁ SENDO IMPLEMENTADO COM TRY/CATCH PORQUE NÃO PODE, eu paro com insistir.

L

Bem… primeiro, cuidado com o “quote”…

Seu erro está em "4 - Exception é tratada no próprio método. Há um catch(Exception ex). ". O catch trata SOMENTE o que está DENTRO do Try. O que está no catch, tem de ser feito separado. Como você “arremessa” um exception, alguém tem de tratar…

Por exemplo, execute esse main e veja o output…

public static void main(String[] args) { try { try { int i = 1/0; System.out.println("Infinito = " + i); } catch (ArithmeticException ae) { throw new Exception("Mas como 1 não divide por 0?", ae); } } catch (Exception e) { e.printStackTrace(); } }

<blockquote>java.lang.Exception: Mas como 1 não divide por 0?

at Mochila.main(Mochila.java:16)

Caused by: java.lang.ArithmeticException: / by zero

at Mochila.main(Mochila.java:13)</blockquote>
ECO2004

leo.andven:
Bem… primeiro, cuidado com o “quote”…

Seu erro está em "4 - Exception é tratada no próprio método. Há um catch(Exception ex). ". O catch trata SOMENTE o que está DENTRO do Try. O que está no catch, tem de ser feito separado. Como você “arremessa” um exception, alguém tem de tratar…

Por exemplo, execute esse main e veja o output…

public static void main(String[] args) { try { try { int i = 1/0; System.out.println("Infinito = " + i); } catch (ArithmeticException ae) { throw new Exception("Mas como 1 não divide por 0?", ae); } } catch (Exception e) { e.printStackTrace(); } }

<blockquote>java.lang.Exception: Mas como 1 não divide por 0?

at Mochila.main(Mochila.java:16)

Caused by: java.lang.ArithmeticException: / by zero

at Mochila.main(Mochila.java:13)</blockquote>

O que escrevi em 4 está certo. Só houve um desentendimento. É claro que o catch trata somente o que ocorre dentro do try (isso se o que aconteceu no try está implementado em algum catch).

Pela divisão de 1/0, gera uma exceção. O método avisou que poderia acorrer, através do throws Exception. Essa exceção ocorre no bloco try. Abaixo, tem o bloco catch(Exception), que, pelo menos, deveria capturar a exceção. Infelizmente, aparece o erro de que não tratei a exceção.

Com relação ao quotes, tou usando certo a ferramenta. Na página que está aparecendo apenas o primeiro.

L

Continuando… :slight_smile:

O escopo das coisas está complicado. Quando você declara que um método solta uma exceção, você está dizendo: alguma coisa dentro de mim (:oops: ) pode soltar uma exceção e eu não estou tratando ela; favor tratar. O método não está declarando que pode acontecer e ser tratado dentro dele. Ele nem deve expor isso se é algo interno (pelos conceitos de encapsulamento et al)

Por que isso está acontecendo no seu código: o “throws ex” dentro do catch está soltando a exception NOVAMENTE. Como não tem nenhum “try” “em cima”/contendo ela, o método tem de declarar isso (porque o catch é feito por Exception, não por Ar.Ex.)

Clareou?

lina

Oi,

Jesus amado. Passei ontem a tarde inteira explicando isso e tem outro tópico tratando o mesmo assunto?!

http://www.guj.com.br/java/52909-exceptions-nao-entendo-sua-utilidade/2#1250392

É por isso que as vezes fico chateada com o fórum =/

Tchauzin!

L

:shock:

Tranca esse, moderadora! Ou o outro!

lina

leo.andven:
:shock:

Tranca esse, moderadora! Ou o outro!

Oi,

Agora não sei mais o que fazer! :shock:

Esse ou o outro? rsrs

Qual esta mais perto da solução?

Tchauzin!

L

Pergunta pro OP… eu acho que nenhum dos dois :roll:

Rodrigo_Sasaki

tranca o outro, ja que o autor é o mesmo… e aqui tiveram umas explicações muito claras sobre o porque o eclipse não indica erro quando não trata uma exceção que se extende a RuntimeException (eu particularmente não sabiaa hehe)

acho que se alguém tiver alguma dúvida quanto a isso ela será sanada olhando esse tópico aqui…

abraço

lina

Oi,

It’s done.

Obrigada!

Tchauzin!

ECO2004

leo.andven:
Continuando… :slight_smile:

O escopo das coisas está complicado. Quando você declara que um método solta uma exceção, você está dizendo: alguma coisa dentro de mim (:oops: ) pode soltar uma exceção e eu não estou tratando ela; favor tratar. O método não está declarando que pode acontecer e ser tratado dentro dele. Ele nem deve expor isso se é algo interno (pelos conceitos de encapsulamento et al)

Por que isso está acontecendo no seu código: o “throws ex” dentro do catch está soltando a exception NOVAMENTE. Como não tem nenhum “try” “em cima”/contendo ela, o método tem de declarar isso (porque o catch é feito por Exception, não por Ar.Ex.)

Clareou?

Ok…entendi…

Grato!

Rodrigo_Sasaki

só faz aquele esquema de editar o seu primeiro post do tópico escrevendo [RESOLVIDO] junto ao assunto pra agradar os moderadores aí hehe

lina

Oi,

A questão não é agradar. A pessoa que geralmente tem a mesma dúvida, saberá que existe em algum post dessa thread a solução! :smiley:

Tchauzin!

L

:thumbup:

O mundo seria melhor sem Exceptions! E, como diria Yoda

Criado 19 de maio de 2011
Ultima resposta 19 de mai. de 2011
Respostas 33
Participantes 7