[Resolvido]Dúvida em relação ao metodo close() em SQL (NullPointerException)

Boa tarde a todos, primeiramente me desculpe se o titulo não deixou muito claro, não consegui pensar em algo melhor. Agora a minha dúvida:

Suponha a seguinte classe:

MinhaClasse.java

[code]public class MinhaClasse extends Pesquisa {

public MinhaClasse() {
	super();
}

public List<Banco> consulta() throws SQLException {
	List<Banco> lista = new ArrayList<Banco>();
	sql = "select * from banco";
	try {
		connection = new ConnectionFactory().getConnection();
		stmt = connection.prepareStatement(sql); // suponhamos que aqui ele
													// lance alguma excessão

		rs = stmt.executeQuery();
		while (rs.next()) {
			Banco banco = new Banco();
			lista.add(banco);
		}
	} catch (SQLException e) {
		throw new RuntimeException(e);
	} finally {
		rs.close();
		stmt.close();
		connection.close();
	}
	return lista;
}

public static void main(String[] args) throws SQLException {
	MinhaClasse m = new MinhaClasse();
	m.consulta();
}

}
[/code]

[code]abstract class Pesquisa {

protected PreparedStatement stmt;
protected String sql;
protected Connection connection;
protected ResultSet rs;

public Pesquisa() {
	connection = new ConnectionFactory().getConnection();
}

}[/code]

Pois bem, se no lugar que eu coloquei o primeiro comentário lançar uma SQLException ele cairá no catch e passar para o finally. Até ai tudo bem, o problema é que se ele lançar uma Exception ali (ou algum lugar antes) ele lançará uma NullPointerException ao tentar invocar o metodo close() já que a variável rs estará apontando para null (já que não foi inicializada por um codigo meu mas sim pelo construtor padrão da classe). Como eu não posso instanciar um objeto do tipo ResultSet não consigo pensar em uma solução para esse problema.

Eu pensei em por um try-catch no finally mas não ficaria elegante. A única forma que eu encontrei seria apagar a classe Pesquisa e refazer todas as classes que herdam dela, transformando rs, stmt, connection e sql em variaveis de escopo.

Existe alguma forma de resolver o meu problema sem ter de usar um try-catch no finally e mantendo a minha classe Pesquisa? Caso não, qual das duas alternativas seria a melhor?

No seu finally vc precisará checar se o objeto é diferente de null, essa é uma das coisas chatas do JAVA

O problema do if é que eu terei que verificar tanto o stmt quanto o rs. Ai no caso, não seria mais facil (ainda sim deselegante) um try-catch dentro do finally?

Sim , você pode verificar a Exception mais de uma vez. tratando uma vez só a SqlException, depois outras, desde que sigam a hierarquia.

} catch (SQLException e) {  
            throw new RuntimeException(e);  
        }  catch (Exception e) {  
            //procedimento para outras exceptions...  
        }

finally {  
            rs.close();  
            stmt.close();  
            connection.close();  
        } 

acho que é algo assim. deixando sempre a Exception mais generica por ultimo. Ai vc trata só a NullPointer ou todas as outras.

[quote=jalonso]Sim , você pode verificar a Exception mais de uma vez. tratando uma vez só a SqlException, depois outras, desde que sigam a hierarquia.

} catch (SQLException e) {  
            throw new RuntimeException(e);  
        }  catch (Exception e) {  
            //procedimento para outras exceptions...  
        }

finally {  
            rs.close();  
            stmt.close();  
            connection.close();  
        } 

acho que é algo assim. deixando sempre a Exception mais generica por ultimo. Ai vc trata só a NullPointer ou todas as outras.[/quote]

Não funciona. Ele lança o NullPointerException APÓS o catch ai ele não pode dar um catch nele.

Ah malz, ele lança a exception já DENTRO do finally, nesse caso vc terá que colocar o try/catch dentro do finally mesmo, conforme vc falou.
Uma alternativa seria popular essas variaveis no construtor da classe Pesquisa(com seus devidos try/catch caso necessario).

[quote=jalonso]Ah malz, ele lança a exception já DENTRO do finally, nesse caso vc terá que colocar o try/catch dentro do finally mesmo, conforme vc falou.
Uma alternativa seria popular essas variaveis no construtor da classe Pesquisa(com seus devidos try/catch caso necessario).[/quote]

Eu pensei na alternativa de popular o ResultSet no construtor mas acabei de descobrir que ResultSet é uma interface portanto não pode ser instanciada. Acho que a única forma mesmo vai ser um try-catch dentro do finally.

Precisa do catch? Um simples if não serviria?

if(rs != null) rs.close()

Pode ser gambiarra para uns, mas acho que fica mais legal do que colocar um try dentro de um finally apenas para isso.

[quote=ErickRAR]Precisa do catch? Um simples if não serviria?

if(rs != null) rs.close()

Pode ser gambiarra para uns, mas acho que fica mais legal do que colocar um try dentro de um finally apenas para isso.[/quote]

O problema é que seriam necessários 2 if’s (um para verificar o PreparedStatement e o outro para verificar o ResultSet). Mas na sua opinião, ainda seria melhor usar 2 if’s?

Obs: Sou um dos que consideram usar if’s dessa forma uma gambiarra, mas, quem nunca usou uma ou outra gambiarra na vida? :lol:

[quote=ErickRAR]Precisa do catch? Um simples if não serviria?

if(rs != null) rs.close()

Pode ser gambiarra para uns, mas acho que fica mais legal do que colocar um try dentro de um finally apenas para isso.[/quote]

Pensando melhor, acho que vou ter de fazer um uso de gambiarras (2 if’s). O código vai ficar mais legivel com 2 if’s do que com 2 try-catch’s (tinha esquecido que seriam necessários 2 try-catch’s, estava pensando apenas em 1).

Agradeço a todos pela ajuda.