java - the - ¿Por qué no funciona try-with-resources con variables de campo?
try with resources java (6)
Esta es mi primera pregunta sobre SO y estoy confundido, ¡todavía no hay una pregunta similar!
Así que la pregunta es:
¿Por qué no funciona try-with-resources con variables de campo?
O en otras palabras: ¿por qué siempre necesito una variable local para eso?
Aquí va un código de ejemplo:
public class FileWriteTest {
public FileWriter file;
public void workingDemo() {
try(FileWriter file = new FileWriter(new File("someFilePath")) {
// do something
} catch (IOException e) {
e.printStackTrace();
}
}
public void notWorkingDemo() {
file = null;
try(file = new FileWriter(new File("someFilePath")) {
// do something
} catch (IOException e) {
e.printStackTrace();
}
}
}
¿Alguien me puede explicar por qué hay esta convención?
Con Java 9, agregaron soporte para intentar con recursos con variables.
// Original try-with-resources statement from JDK 7 or 8
try (Resource r1 = resource1;
Resource r2 = resource2) {
// Use of resource1 and resource 2 through r1 and r2.
}
// New and improved try-with-resources statement in JDK 9
try (resource1;
resource2) {
// Use of resource1 and resource 2.
}
https://blogs.oracle.com/darcy/more-concise-try-with-resources-statements-in-jdk-9
En primer lugar, creo que sería una mala práctica tener una variable / recurso que se utiliza en varios lugares. Si no se abre en el try
, no puede cerrarlo después, si se abre allí, no necesitará una variable no local. Esto lleva a "segundo": si ya tiene un recurso abierto, entonces necesita cerrarlo explícitamente en otro lugar, de lo contrario, el cierre automático no sabría si está abierto o no.
Entonces, en mi humilde opinión, solo tiene sentido manejarlo de la manera especificada en la especificación.
Puede tener que ver con la coherencia con las especificaciones del idioma. Cada vez que se declara una variable entre dos corchetes, se encapsula dentro y no se puede acceder desde el exterior:
anything
{
int var;
}
// cannot access var from here!
¿Por qué deberías intentar {} ser una excepción?
Sospecho que los diseñadores consideraron que usar un campo es una mala idea, ya que esto permite que el objeto escape de la región de uso. es decir, solo es válido en el bloque try, por lo que no debería poder acceder a él en ningún otro lugar.
Una variable de instancia se puede cambiar en cualquier momento durante la ejecución del bloque try-with-resources. Esto rompería su invariante y evitaría la limpieza. Tenga en cuenta que la variable local es implícitamente final, por el mismo motivo.
Por cierto, una pregunta mejor es por qué Java nos obliga a declarar una variable local, incluso si no nos referimos a ella dentro del bloque. C #, por ejemplo, no requiere esto.
La sección 14.20.3 de la especificación del lenguaje Java indica que solo funcionará con variables locales.
¿Por qué es esto? Mi conjetura es verificar la asignación definida y el escape (la variable local no se escapa al alcance de otro método). Un campo puede ser inicializado en cualquier parte de la clase. Mi conjetura es que al validar es una variable local, es mucho más simple de analizar.