2012-02-19 17 views
14

Tengo una variable que no debe cambiar su valor después de que se ha inicializado, por lo que quiero definirlo como una variable final.java: cómo declarar final una variable que se inicializa dentro de un bloque try - catch?

el problema es que la variable tiene que ser inicializado dentro de un bloque try, por lo que obtener los siguientes problemas:

tengo el siguiente código:

Connection conn = null; 
try { 
    conn = getConn(prefix); 
    [...do some stuff with conn...] 
} catch (Exception e) { 
    throw new DbHelperException("error opening connection", e); 
} finally { 
    closeConnection(conn); 
} 

Si declaro la variabale como definitiva , sin inicializarlo a nulo, obtengo un 'Conn de la variable local puede no haberse inicializado' en el bloque finally. Por otro lado, si declaro que es definitivo y lo inicializo en nulo, aparece el error 'La connotación de la variable local final no se puede asignar' en el bloque try.

EDIT: después de recibir respuesta LXX, me encontré con esta versión

try { 
    final Connection conn = conn = getConn(prefix); 
    try { 
     return selectAll(conn, sql, params); 
    } catch (Exception e) { 
     throw new DbHelperException("error executing query", e); 
    } finally { 
     closeConnection(conn); 
    } 
} catch (Exception e) { 
    throw new DbHelperException("error opening connection", e); 
} 

Así que esta debe ser la manera de hacerlo?

-

lección aprendida:

Creo que la respuesta correcta a la pregunta es la que LXX dio, pero en este caso supongo que los contras de la declaración de las outweights finales variables Es beneficios ...

-

EDIT: encontrado dos preguntas sobre desbordamiento de pila sobre el momento de uso final

When should one use final for method parameters and local variables?

Using "final" modifier whenever applicable in java

+0

¿Qué tal anexar 'final Connection finalConn = conn;' a su código? – biziclop

+0

¿Por qué necesita ambos 'try's? ¿Por qué no tener solo un solo try-catch en el que obtienes la conexión y la utilizas para seleccionar todo? – yshavit

+0

Me pregunto por qué crees que es tan importante declarar esto como definitivo. A mí me parece un poco tonto y naggy. Si yo fuera un usuario, y llamé a su método para obtener una conexión, no veo ningún motivo por el que desee suprimir eso al cambiarlo. Y si lo hiciera, argumentaría que las consecuencias deberían estar en el usuario. – duffymo

Respuesta

7

Se podía manejar las excepciones con mayor precisión. Si obtiene una excepción abriendo la conexión, no tiene que cerrarla en el bloque final, supongo. Si obtiene una excepción después de eso, en el bloque try, y maneja la excepción en un nuevo bloque try-catch anidado, no necesita definir la variable afuera. Algo como:

try { 
     final Connection conn = getConn(prefix); 
     try { 
      //code using conn 
     } catch (Exception e) { 

     } finally { 
      closeConnection(conn); 
     } 
    } catch (DbHelperException e) { 
     throw new DbHelperException("error opening connection", e); 
    } 
+3

+1, esta es probablemente la solución más limpia. – biziclop

+0

Sí, entiendo lo que quiere decir, supongo que si hay una excepción que abre la conexión, la conexión no se pudo abrir, por lo que no es necesario cerrarla. Vine con otra versión del código, gracias a su respuesta, vuelva a verificar la pregunta ... – opensas

+0

@opensas Si hay una excepción en la llamada 'getConn()', si la conexión se abrió o no, 'conn' definitivamente será nulo, por lo que no podrá cerrarlo de todos modos. – biziclop

-2

Se puede tratar asignándole tanto en la captura y, finalmente, los bloques? Al igual que :

Connection connTemp = null; 
final Connection conn; 
try { 
    connTemp = getConn(prefix); 
} catch (Exception e) { 
    throw new DbHelperException("error opening connection", e); 
} finally { 
    closeConnection(conn); 
} 
conn = connTemp; 
+0

una vez declarado como final no se puede cambiar en ningún lado, ese es el propósito –

+0

Se ha actualizado para usar una variable de temperatura. – AlexanderZ

-1

¿Por qué quieres que sea definitiva? Si quieres pasarlo a una clase interna anónima, que podría hacer:

Connection conn = null; 
try { 
    conn = getConn(prefix); 
    final Connection finalConn = conn; 
    // pass it to inner class here 
} catch (Exception e) { 
    throw new DbHelperException("error opening connection", e); 
} finally { 
    closeConnection(conn); 
} 

El único problema (y bastante grande) con esta solución es que cierre su conexión tan pronto como salga este bloque. Entonces, a menos que usted declare y llame inmediatamente a su clase interna de anon, este patrón no va a funcionar.

De cualquier manera, probablemente reformularía todo el asunto si fuera usted, haciendo prefix final en su lugar y delegando el manejo de la conexión a la clase interna anon.

+0

¡Uy! tienes razón, (por cierto, atrapaste un error desagradable, gracias) - actualicé la pregunta ... – opensas

+2

y quiero definirlo como definitivo, solo para decirle al compilador que la variable conn no debe cambiar su valor después de ser inicializada ... – opensas

2

¿Qué tal esto?

Connection temp = null; 
try { 
    temp = getConn(prefix); 
} catch (Exception e) { 
    throw new DbHelperException("error opening connection", e); 
} finally { 
    closeConnection(conn); 
} 
final Connection conn = temp; 
+0

También podría seguir adelante y establecer la temperatura en 'null' de esa manera no la use más. – Michael

+4

Esta es una buena forma de obtener una referencia 'final' a una conexión que ya está cerrada. :) – biziclop

+1

@Michael deja que la JVM lo maneje. –

Cuestiones relacionadas