java - scanner - Fugas de recursos: ''en'' nunca se cierra
resource leak teclado is never closed (13)
¿Por qué Eclipse me da el calentamiento "Fugas de recursos: ''en'' nunca se cierra ''en el siguiente código?
public void readShapeData() {
Scanner in = new Scanner(System.in);
System.out.println("Enter the width of the Rectangle: ");
width = in.nextDouble();
System.out.println("Enter the height of the Rectangle: ");
height = in.nextDouble();
Como han dicho otros, debe llamar ''cerrar'' en clases IO. Añadiré que este es un lugar excelente para usar el bloque try - finally sin atrapar, como este:
public void readShapeData() throws IOException {
Scanner in = new Scanner(System.in);
try {
System.out.println("Enter the width of the Rectangle: ");
width = in.nextDouble();
System.out.println("Enter the height of the Rectangle: ");
height = in.nextDouble();
} finally {
in.close();
}
}
Esto asegura que su escáner esté siempre cerrado, garantizando la limpieza adecuada de los recursos.
De manera equivalente, en Java 7 o superior, puede usar la sintaxis "try-with-resources":
try (Scanner in = new Scanner(System.in)) {
...
}
Debe close su escáner cuando haya terminado con él:
in.close();
El escáner debe estar cerrado. Es una buena práctica cerrar Readers, Streams ... y este tipo de objetos para liberar recursos y grandes pérdidas de memoria; y hacerlo en un bloque final para asegurarse de que estén cerrados incluso si se produce una excepción al manipular esos objetos.
En general, las instancias de las clases que se ocupan de E / S deben cerrarse después de que haya terminado con ellas. Entonces, al final de su código, puede agregar in.close()
.
Le indica que debe cerrar el escáner instanciado en System.in
con Scanner.close()
. Normalmente, todos los lectores deben estar cerrados.
Tenga en cuenta que si cierra System.in
, no podrá leer de nuevo. También puedes echar un vistazo a la clase de la Console
.
public void readShapeData() {
Console console = System.console();
double width = Double.parseDouble(console.readLine("Enter the width of the Rectangle: "));
double height = Double.parseDouble(console.readLine("Enter the height of the Rectangle: "));
...
}
Necesitas llamar a in.close()
, en un bloque finally
para asegurarte de que ocurra.
De la documentación de Eclipse, aquí es por qué marca este problema en particular (el énfasis es mío):
Se considera que las clases que implementan la interfaz java.io.Closeable (desde JDK 1.5) y java.lang.AutoCloseable (desde JDK 1.7) representan recursos externos, que deben cerrarse con el método close (), cuando ya no sean necesarios.
El compilador Eclipse Java puede analizar si el código que utiliza dichos tipos se adhiere a esta política.
...
El compilador marcará [violaciones] con "Pérdida de recursos: ''secuencia'' nunca se cierra".
Explicación completa here
Porque no cierras tu escáner
in.close();
Si está utilizando JDK7 u 8, puede usar try-catch con recursos. Esto cerrará automáticamente el escáner.
try ( Scanner scanner = new Scanner(System.in); )
{
System.out.println("Enter the width of the Rectangle: ");
width = scanner.nextDouble();
System.out.println("Enter the height of the Rectangle: ");
height = scanner.nextDouble();
}
catch(Exception ex)
{
//exception handling...do something (e.g., print the error message)
ex.printStackTrace();
}
agregar private static Scanner in;
realmente no soluciona el problema, solo borra la advertencia. Hacer que el escáner sea estático significa que permanece abierto para siempre (o hasta que la clase esté descargada, lo que casi es "para siempre"). El compilador ya no te avisa más, ya que le dijiste "mantenlo abierto para siempre". Pero eso no es lo que realmente quería, ya que debe cerrar los recursos tan pronto como ya no los necesite.
HTH, Manfred.
// An InputStream which is typically connected to keyboard input of console programs
Scanner in= new Scanner(System.in);
La línea superior invocará la clase Constructor of Scanner con el argumento System.in, y devolverá una referencia al objeto recién construido.
Está conectado a un flujo de entrada que está conectado al teclado, por lo que ahora, en tiempo de ejecución, puede tomar la entrada del usuario para realizar la operación requerida.
//Write piece of code
Para eliminar la fuga de memoria -
in.close();//write at end of code.
Scanner sc = new Scanner(System.in);
//do stuff with sc
sc.close();//write at end of code.
in.close();
scannerObject.close();
Cerrará el Scanner
y cerrará la advertencia.
private static Scanner in;
Lo arreglé declarando como una variable de clase de escáner estático privado. No estoy seguro de por qué lo solucionó, pero eso es lo que el eclipse me recomendó.