Java – Escáner de cierre y fuga de recursos

Estoy aprendiendo Java y trabajando en algunos proyectos por diversión. Un problema con el que me he encontrado es que cuando uso un objeto Scanner Eclipse me advierte que:

Fuga de recursos: ‘escaneo’ nunca se cierra.

Entonces, agregué un scan.close(); al final de mi código y eso se encarga de la advertencia.

El problema viene porque tengo otras clases en el mismo paquete que también usan objetos de escáner y Eclipse me dice que cierre el escáner en esas clases, respectivamente. Sin embargo, cuando lo hago, parece que cierra TODOS los objetos del escáner y obtengo errores durante el tiempo de ejecución.

Aquí hay un ejemplo de lo que causa el error:

 import java.util.Scanner; public class test2 { public static void main(String [] args) { Scanner scan = new Scanner(System.in); int test = 0; do { //Do stuff test = scan.nextInt(); System.out.println(test); scanTest scanTest = new scanTest(); scanTest.test(); } while (test != 0); scan.close(); } } import java.util.Scanner; public class scanTest { public void test() { Scanner scanner = new Scanner(System.in); int blah = scanner.nextInt(); System.out.println(blah); scanner.close(); } } 

Después de que el escáner se cierra en la clase scanTest y el bucle do en test2 se ingresa nuevamente, se produce un error en la línea test = scan.nextInt();

Traté de mover la creación del objeto del escáner al ciclo do solo para hacer un nuevo objeto cada vez, pero el error aún ocurre.

No estoy seguro de por qué sucede esto ni de cómo puedo asegurarme de que todos mis objetos de E / S estén cerrados sin problemas.

Una publicación que encontré mencionó que cuando System.in está cerrado no puedo volver a abrirlo. Si este es el caso, ¿solo tendría que asegurarme de que un objeto del escáner con System.in se cierre al final del progtwig y que se repitan todas las demás advertencias del escáner en otras clases? ¿O eso dejaría abiertos todos los objetos del escáner (mal)?

Primero, esto no es una pérdida de memoria.

En segundo lugar, cuando cierra un contenedor de secuencias, la implementación predeterminada es para que cierre la secuencia que envuelve. Esto significa que la primera vez que cierra el escáner (tal como está escrito), sí, cierra System.in.

En general, a uno le gustaría evitar cerrar System.in si quisieran leer System.in nuevamente. La mejor manera de hacerlo depende de su progtwig.

Uno podría copiar la información de System.in en un buffer de algún tipo y luego escanear el buffer. Es posible que uno no cierre el escáner, reutilizándolo en otras ubicaciones. Uno incluso podría quitar la referencia del escáner para la recolección de basura y crear múltiples nuevos escáneres en System.in.

Estas soluciones no son todas equivalentes, algunas se consideran mucho mejores que otras; pero, todo depende del progtwig de llamadas. Experimente con unos pocos, y si se encuentra con un problema, abra una nueva pregunta de StackOverflow donde muestre las partes relevantes de su código, una descripción del problema, la entrada de ejemplo y el resultado incorrecto (junto con el resultado deseado).

Buena suerte.

Sí, cuando cierra un escáner, estará cerrando el flujo subyacente (en este caso System.in). Para evitar esto, cree una variable global de escáner que pueda ser utilizada por todas las clases o tenga un punto central para apagar el escáner (justo antes de que el progtwig salga sería ideal)

No nombre todos los escáneres de la misma. Si tienes múltiples en una cosa como esta:

 import java.util.Random; import java.util.Scanner; public class DayThree { public static void main(String[] args) { **Scanner textScanner = new Scanner(System.in);** // boolean operands // String(or objects) .equals() "this".equals("that") false // primitive data types == 'a'=='a' -> true 5==6 false // != 'a'!='a' -> false 5!=6 true // ! !(true) -> false !(false) true // > 5 > 4 -> true 'a' > 'b' false // < 5 < 4 -> false // < = // >= // && -> and 5 < 6 && 7 > 10 -> false // if either side of and is false the outcome is false // || -> or 5 < 6 || 7 > 10 -> true // if either side of or is true the outcome is true //System.out.println(!(5 < 10) && (7>3) || (true && false || true)); /* < -- this is a multi line comment System.out.println("What is the most amazing show on tv this week? "); String show = textScanner.nextLine().toLowerCase(); //this is case sensitive show = show.toLowerCase(); // changes the strng to a lowercase version show = show.toUpperCase(); if(show.equalsIgnoreCase("game of thrones")){ // .equalsIgnoreCase( ignores caps/lower) System.out.println("Yes it is!"); } else{ System.out.println("You are wrong."); System.out.println(show + " is clearly inferior to Game of Thrones."); } System.out.println("Who is your favorite character in " + show + "."); String character = textScanner.nextLine().toLowerCase(); if(character.contains("dragon")){ System.out.println("CGI magic is so cool!"); } else if(character.contains("lanister")){ System.out.println("Wrong house."); } else{ System.out.println(character + "is pretty cool I guess..."); } */ // asdf alternate multi line comment use ctrl + / on highlighted text. // doing this a second time undoes the comment // sdaf // asdf // asdf // asdf // 1. ask about favorite something (pet) // 2. save that into a string all lowercase // 3. have a series of if else (x3) and else statements about the something //NOTE: DO NOT END CONDITIONALS WITH ; example: if(boolean); IS WRONG. **Scanner numScanner = new Scanner(System.in);** // the variable tells you what to use it for Random rand = new Random(); // this makes a new random object System.out.println("Pick a number."); int num = numScanner.nextInt(); int sNum = rand.nextInt(9) + 1; // gives me a random num between 1-10 // nextInt(bound)gives you a num from 0-bound //adding one gives you a num from 1 - bound + 1 if(num > sNum){ System.out.println("Too high"); System.out.println("The number was " + sNum); } else if(num < sNum){ System.out.println("Too low"); System.out.println("The number was " + sNum); } else{ System.out.println("Wow are you psychic? "); } textScanner.close(); numScanner.close(); }//main method } 

Ponga el *scanner name goes here*.close(); para cada uno de sus escáneres Si todos tienen el mismo nombre, cambie los que hacen algo diferente y otro escáner.