Tratamento de exceções

3 respostas
M

Eae pessoal, tava dando uma estudada em tratamento de exceções e me surgiram algumas dúvidas.

O código é este:

import java.util.InputMismatchException;
import java.util.Scanner;

public class DivideByZeroWithExceptionHandling {

	public static int quociente(int numerador, int denominador) 
			 throws ArithmeticException
	{
		
		return numerador / denominador;
		
	}
	
	public static void main(String[] args) {
		
		Scanner input = new Scanner(System.in);		
		boolean continuaLoop = true;
		
		do {

			try {
								
				System.out.print("Entre com o numerador: ");
				int numerador = input.nextInt();
				
				System.out.print("Entre com o denominador: ");
				int denominador = input.nextInt();
				
				int resultado = quociente(numerador, denominador);
				
				System.out.printf("%d / %d = %d ", numerador, denominador, resultado);
				
				continuaLoop = false;
				
			}
			
			catch (ArithmeticException arithmeticException ) {
			
				System.err.printf("\nErro: %s\n", arithmeticException);
				System.out.println("Zero é um denominador invalido. Tente denovo.\n");
				
			}
			
			catch (InputMismatchException inputMismatchException) {
				
				System.err.printf("\nErro: %s\n", inputMismatchException);
				System.out.println("Não digite caracteres que não sejam números inteiros. Tente denovo.\n");
				
				input.nextLine();
				
			}
			
		} while (continuaLoop);
			
	}
	
}

1º Por que só o catch que trata o InputMismatchException precisa “limpar” o que o usuário digitou com o input.nextLine() ?

2º Se eu rodar esse código no eclipse - indigo aqui ele sai com um erro de execução depois que eu tento digitar um denominador como zero ou se digito uma String ao invés de um um int. O resultado é este( só muda o nome da exceção se eu colocar o denominador com zero ou uma String ao invés de um int ):

Erro: Zero é um denominador invalido. Tente denovo.

Entre com o numerador: java.lang.ArithmeticException: / by zero

Agora se eu mudar os System.err para System.out ele roda certinho.

Alguem poderia me explicar o que há de errado?

3 Respostas

tuliomonteazul
1º Por que só o catch que trata o InputMismatchException precisa "limpar" o que o usuário digitou com o input.nextLine() ?

De acordo com a documentação da InputMismatchException, a exceção é lançada pela classe Scanner, diferente da Arithmetic, que é lançada pela sua operação de divisão. Portanto, como foi lançada pela Scanner durante a execução do método nextInt(), este método não completou a sua execução e portanto o caractere inválido que você digitou ainda não foi lido. Então o nextLine() é um artifício (gambiarra) para ler o caractere inválido e removê-lo da pilha de leitura.

2º Se eu rodar esse código no eclipse - indigo aqui ele sai com um erro de execução depois que eu tento digitar um denominador como zero ou se digito uma String ao invés de um um int. O resultado é este( só muda o nome da exceção se eu colocar o denominador com zero ou uma String ao invés de um int ): view plaincopy to clipboardprint?
Erro: Zero é um denominador invalido. Tente denovo.  
  
Entre com o numerador: java.lang.ArithmeticException: / by zero
Agora se eu mudar os System.err para System.out ele roda certinho.

O problema que você indicou é que as mensagens emitidas pelo System.err e pelo System.out estão entrelaçadas, não é?
Isso acontece por que System.err e System.out são duas variáveis que referenciam duas instâncias diferentes do tipo PrintStream. Cada uma dessas instâncias pode acessar o seu Console independente da outra. Portanto, quando você executa as linhas 39 e 40 do seu programa, os métodos printf e println utilizam dois canais de comunicação (stream) diferentes para acessar um mesmo recurso (Console). Quando você utiliza apenas System.err ou System.out, estará utilizando apenas um canal de comunicação, e portanto, a ordem das mensagens que você enviou ao Console será mantida. É parecido com um problema de multi-thread.

M

Só mais uma dúvida em relação ao throws.
O livro que eu estou lendo diz que existem dois tipos de exceções: as verificadas e as não verificadas.
As verificadas são aquelas que derivam da classe Exception mas não da RunTimeException, e as não verificadas são aquelas que derivam da RumTimeException. Quando ocorrer uma exceção verificada o compilador exige que se obedeça a regra “declare ou capture”. Declarar com o throws ou capturar com o try catch. Porém, o livro não diz nada, até o momento, sobre as não verificadas. E pelo que eu andei testando eu posso omitir o throws, nesse exemplo que eu postei, no método quociente que não há alteração no resultado(pois ArithmeticException é uma exceção não verificada).
Então a minha dúvida é esta: Eu posso sempre omitir a cláusula throws quando o método lançar exceções não verificadas ou eu tenho que coloca-lo sempre por causa de algum tipo de “convenção” para clareza de código ou alguma coisa assim?

Obs* Caso alguém verifique algum erro no meu raciocínio me corrija por favor.
Obrigado.

tuliomonteazul

As exceções não verificadas são de uma natureza diferente das verificadas.
Na maioria dos casos não vai fazer sentido colocar um throws para elas.
Imagine se a gente tivesse que colocar um try/catch para IndexOutOfBoundsException toda vez que fossemos trabalhar com posições de array/string/etc.

Criado 13 de julho de 2011
Ultima resposta 18 de jul. de 2011
Respostas 3
Participantes 2