Re-lançamento de erro mais preciso e possíveis problemas (Java 7)

Ao capturar e lançar os erros capturados o Java 7 tem uma verificação mais precisa. Ele consegue descobrir em tempo de compilação quais são os erros mais específicos e ao invés de fazer o lançamento de um erro genérico, você pode fazer o lançamento dos erros específicos. Esse recurso é conhecido como: more precise rethrow. Parece meio complicado de se entender, mas na prática é mais simples. Então vamos ver um exemplo.

Nas versões anteriores de Java quando queríamos relançar os erros ocorridos fazíamos da seguinte maneira:

	public void metodoQueLancaExcecao() throws AException, BException {
		try {
			int a = 0;
			if (a == 0) {
				throw new AException();
			} else {
				throw new BException();
			}
		} catch (AException e) {
			throw e;
		} catch (BException e) {
			throw e;
		}
	}

Ou quando tínhamos  várias possíveis exceptions, podíamos capturar com uma mais genérica e relançar ela. Por exemplo:

	public void metodoQueLancaExcecao() throws Exception {
		try {
			int a = 0;
			if (a == 0) {
				throw new AException();
			} else {
				throw new BException();
			}
		} catch (Exception e) {
			throw e;
		}
	}

O problema dessa última solução é que o tratamento da classe que chama esse método se torna pior, pois não sabemos qual erro poderá ocorrer, e na primeira solução se tivermos um número muito grande de exceções a serem re-lançadas o código se torna extenso. Para resolver esse problema, no Java 7 podemos fazer da seguinte maneira:

	public void metodoQueLancaExcecao() throws AException, BException {
		try {
			int a = 0;
			if (a == 0) {
				throw new AException();
			} else {
				throw new BException();
			}
		} catch (Exception e) {
			throw e;
		}

	}

Esse código não compila no Java 6 e inferiores, pois o compilador irá informar que a exceção Exception não está sendo tratada. No Java 7 ele "percebe" que as única exceções que estão sendo lançadas são a AException e a BException e portanto não obriga o tratamento de nenhuma outra.

Entretanto esse novo recurso pode trazer problemas de incompatibilidades na compilação de códigos feitos nas outras versões de Java, por exemplo:

	public void metodoQueLancaExcecao() throws A {
		try {
			throw new FilhaDeA();
		} catch (A e) {
			try {
				throw e;
			} catch (OutraFilhaDeA anotherException) { // Não alcançável
				System.out.println("Deu pau!");
			}
		}
	}

Esse código compila na versão Java 6 e inferiores, mas não compila na versão 7. Isso pra mim é um perigo muito grande. Pois no Java 7 o último catch nunca será executado, pois eu sei que o "throw e" é do tipo FilhaDeA e como o tratamento é mais preciso, eu sei que nunca vou capturar erros do tipo OutraFilhaDeA. Já no Java 6 e inferiores isso não ocorre (eu posso tratar erros mais específicos).

Segundo a especificação do Project Coin/JSR 334:

An examination of millions of lines of code in a diverse set of projects, including dozens of members of the Qualitas Corpus and the JDK, found no instances where these conditions occurred.

Ou seja, eles nunca encontraram código em que isso ocorria. Se por acaso ao tentar compilar um programa existente do Java 6 ou inferior em Java 7 e tiver um erro parecido com esse:

Unreachable catch block for OutraFilhaDeA. This exception is never thrown from the try statement body

Já sabe o que pode ser.

Sobre: Thiago Galbiatti Vespa

Thiago Galbiatti Vespa é mestre em Ciências da Computação e Matemática Computacional pela USP e bacharel em Ciências da Computação pela UNESP. Coordenador de projetos do JavaNoroeste, membro do JCP (Java Community Process), consultor Oracle, arquiteto de software de empresas de médio e grande porte, palestrante de vários eventos e colaborador de projetos open source. Possui as certificações: Oracle Certified Master, Java EE 5 Enterprise Architect – Step 1, 2 and 3; Oracle WebCenter Portal 11g Certified Implementation Specialist; Oracle Service Oriented Architecture Infrastructure Implementation Certified Expert; Oracle Certified Professional, Java EE 5 Web Services Developer; Oracle Certified Expert, NetBeans Integrated Development Environment 6.1 Programmer; Oracle Certified Professional, Java Programmer; Oracle Certified Associate, Java SE 5/SE 6