Durante uma aula surgiu uma implementacao feita por um aluno, creditos ao Matheus Cezar, onde se encaixa uma refatoracao bem interessante: substituir excecao por teste.A cronica e a seguinte: considere um metodo que retorne um elemento de uma colecao pelo indice ou nulo caso nao exista o dado elemento. Um codigo cobaia pode ser visto a seguir.public class Main { static String[] opcoes = {"zero", "um", "dois"}; public static void main(String[] args) { } // retornar a opcao ou nulo caso nao seja encontrada static String getOpcao(int numero) { // implementacao aqui }}Existem varios modos de cumprir a API do metodo, uma delas e introduzindo um mau cheiro no codigo, utilizando a captura de excecoes como desvio condicional. E bem simples, veja a seguir:public class Main { static String[] opcoes = {"zero", "um", "dois"}; public static void main(String[] args) { System.out.println(getOpcao(9)); } // retornar a opcao ou nulo caso nao seja encontrada static String getOpcao(int numero) { try { return opcoes[numero]; } catch (ArrayIndexOutOfBoundsException e) { return null; } }}Esta e uma implementacao intuitiva a primeira vista, note que ela resolve o problema, ou seja, neste exemplo e impresso null, pois como nao ha o indice 9 o codigo opcoes.get(numero) lanca a excecao ArrayIndexOutOfBoundsException que e capturada e suprimida, retornando null na situacoes excepcionais.Existem um detalhe importante a respeito de excecoes, elas introduzem um overhead, ja que cada vez que acontecem, alem do bloco condicional um objeto e criado para representar a excecao.O que eu quero dizer e que esta implementacao, baseada na captura da excecao, tem baixa performance se comparada com a realizacao de um teste, que e a refatoracao proposta e inclusive documentada no livro do Fowler.Escrevi um pequeno benchmark para instrumentar este codigo, veja a seguir:public class Main { static String[] opcoes = {"zero", "um", "dois"}; public static void main(String[] args) { long inicio = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { getOpcao(9); } System.out.println((System.currentTimeMillis() - inicio) + "ms"); } // retornar a opcao ou nulo caso nao seja encontrada static String getOpcao(int numero) { try { return opcoes.get[numero]; } catch (ArrayIndexOutOfBoundsException e) { return null; } }}O tempo decorrido para executar 10000 (dez mil) consultas e de 110ms no meu modesto notebook equipado com um Intel Pentium Dual Core.A refatoracao a seguir torna o codigo mais claro e tambem mais rapido, e a substituicao de excecao por teste, veja a seguir:public class Main { static String[] opcoes = {"zero", "um", "dois"}; public static void main(String[] args) { long inicio = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { System.out.println(getOpcao(9)); } System.out.println((System.currentTimeMillis() - inicio) + "ms"); } // retornar a opcao ou nulo caso nao seja encontrada static String getOpcao(int numero) { if (numero >= 0 && numero < opcoes.length) return opcoes[numero]; return null; }}Esta implementacao executa em 5ms em media, bem melhor do que os 110ms anteriores, nao? A mecanica e simples, em vez de confiar no catch nos fazemos um teste para verificar a validade do parametro.E isso, deixe seu comentario se quiser. Esses dias estava conversando na aula de