Entendendo tratamento de exceções, try, catch com Java

Foto do autor Nelio Alves
Nelio Alves
Compartilhar
Compartilhar no LinkedInCompartilhar no FacebookCompartilhar no XCompartilhar no WhatsApp
Imagem banner do post

Em muitos programas, especialmente nos primeiros contatos com orientação a objetos, é comum surgir a dúvida: onde devem ficar as regras de validação? Na aplicação? Dentro da classe de domínio? Neste post, você vai entender, usando um exemplo prático, como o tratamento de exceções com try e catch em Java ajuda a organizar responsabilidades, tornar o código mais claro e reforçar os princípios de encapsulamento, coesão, e delegação na construção de sistemas.

O problema: cálculo de financiamento com regras de negócio

Os dados de um financiamento são:

  • Valor total do financiamento.
  • Valor pago na entrada.
  • Número de parcelas.

Deseja-se fazer um programa que, informados os dados de um financiamento, mostre quanto é o valor de cada prestação do financiamento. O valor da prestação é o valor total menos o valor de entrada, dividido pelo número de parcelas.

Exemplo:

Entrada:

  • Valor total = 1000
  • Valor da entrada = 300
  • Quantidade de prestações = 10

Saída = 70 (pois descontando 300 de entrada ao valor total de 1000, sobra 700, que dividido em 10 prestações resulta em parcelas de 70 cada)

O programa ainda deve verificar as seguintes regras, informando uma mensagem de erro caso alguma regra seja violada:

  • O valor da entrada deve ser pelo menos 20% do valor total do financiamento.
  • O número mínimo de parcelas deve ser 6.

Aqui surge uma pergunta importante: onde essas validações devem ficar? Na aplicação? Ou dentro do próprio objeto de domínio?

A solução ruim: validação espalhada na aplicação

Primeiro, vejamos uma implementação possível.

Copiar
public class Financiamento {

	public Double valorTotal;
	public Double entrada;
	public Integer parcelas;
	
	public Financiamento(double valorTotal, double entrada, int parcelas) {
		this.valorTotal = valorTotal;
		this.entrada = entrada;
		this.parcelas = parcelas;
	}

	public double prestacao() {
		return (valorTotal - entrada) / parcelas;
	}
}
Copiar
public class ProgramaPrincipal {

	public static void main(String[] args) {
		
		double valorTotal = 1000.0;
		double entrada = 300.0;
		int parcelas = 10;
		
		if (entrada < valorTotal * 0.2) {
			System.out.println("A entrada deve ser pelo menos 20% do valor total");
		}
		else if (parcelas < 6) {
			System.out.println("O número mínimo de parcelas deve ser 6");
		}
		else {
			Financiamento f = new Financiamento(valorTotal, entrada, parcelas);
			System.out.println(f.prestacao());
		}
	}
}

Por que essa solução é ruim?

Existem alguns problemas importantes aqui:

  1. A lógica de validação está na aplicação (ProgramaPrincipal) e não no domínio (Financiamento).
  2. O objeto Financiamento pode ser criado em estado inválido se alguém esquecer de validar.
  3. O uso de if-else encadeados não é a forma mais clara e escalável de expressar regras de negócio.
  4. A responsabilidade está espalhada: parte da regra está fora da classe que representa o conceito.

Em orientação a objetos, o objeto deve ser responsável por manter sua própria consistência. Se um financiamento não pode existir com entrada menor que 20% ou com menos de 6 parcelas, então essa regra pertence ao próprio financiamento.

A solução boa: validação no domínio com exceções

Agora veja uma abordagem mais adequada.

Copiar
public class Financiamento {

	public Double valorTotal;
	public Double entrada;
	public Integer parcelas;
	
	public Financiamento(double valorTotal, double entrada, int parcelas) {
		
		if (entrada < valorTotal * 0.2) {
			throw new RuntimeException("A entrada deve ser pelo menos 20% do valor total");
		}
		if (parcelas < 6) {
			throw new RuntimeException("O número mínimo de parcelas deve ser 6");
		}
		
		this.valorTotal = valorTotal;
		this.entrada = entrada;
		this.parcelas = parcelas;
	}

	public double prestacao() {
		return (valorTotal - entrada) / parcelas;
	}
}
Copiar
public class ProgramaPrincipal {

	public static void main(String[] args) {
		
		double valorTotal = 1000.0;
		double entrada = 300.0;
		int parcelas = 10;
		
		try {
			Financiamento f = new Financiamento(valorTotal, entrada, parcelas);
			System.out.println(f.prestacao());
		}
		catch (RuntimeException e) {
			System.out.println(e.getMessage());
		}
	}
}

Por que essa solução é melhor?

Agora temos melhorias importantes:

  1. O próprio objeto Financiamento garante sua consistência.
  2. Não é possível criar um financiamento inválido.
  3. A aplicação apenas tenta usar o objeto e trata possíveis erros.
  4. As regras de negócio estão centralizadas no domínio.

Essa é uma aplicação prática de encapsulamento: o objeto protege seu próprio estado.

Entendendo o papel do try e catch

Quando usamos throw, estamos interrompendo o fluxo normal do programa e sinalizando que algo deu errado.

O bloco try indica que estamos executando um trecho de código que pode gerar uma exceção.

O bloco catch captura essa exceção e permite que tratemos o erro de forma controlada.

No nosso exemplo:

  • Se os dados forem válidos, o financiamento é criado e a prestação é exibida.
  • Se alguma regra for violada, a exceção é lançada.
  • O catch intercepta a exceção e exibe a mensagem apropriada.

Esse mecanismo separa claramente:

  • Regra de negócio (domínio)
  • Tratamento de erro (camada de aplicação)

Assista a aula em vídeo com o prof. Dr. Nelio Alves no Youtube:

Conclusão: exceções como ferramenta de modelagem

Tratamento de exceções em Java não serve apenas para evitar que o programa "quebre". Ele é uma ferramenta de modelagem.

Ao lançar exceções dentro do domínio, estamos dizendo:

"Este objeto não pode existir nesse estado."

Isso torna o código:

  • Mais seguro
  • Mais organizado
  • Mais alinhado com os princípios de orientação a objetos
  • Mais fácil de evoluir

Entender try, catch e throw é entender como proteger a integridade do seu modelo de negócio. E essa é uma das diferenças fundamentais entre código que apenas funciona e código bem projetado.

Foto do autor Nelio Alves
Nelio Alves
Desenvolvedor e Professor
Olá, meu nome é Nelio Alves. Sou graduado em Ciência da Computação e possuo mestrado e doutorado em Engenharia de Software pela Universidade Federal de Uberlândia. Trabalho como desenvolvedor e professor de programação há mais de 20 anos, e sou um dos educadores de tecnologia mais influentes da Internet com mais de 500 mil alunos online.