Error using scanner.close()

Asked

Viewed 1,739 times

3

I’m trying to run this code in Java, using Eclipse. The same runs once normal. When trying to repeat the operation (choosing option 1) gives error as shown below.

If I remove the scanner.close(); it works normal by running several times.

I’ve found something about it on the Internet, including here, but I didn’t understand and I couldn’t solve the problem.

Someone could help by clarifying why the error occurs and how to resolve the error?

import java.util.Scanner;

public class Exercicio{

    public int menu() {
        Scanner scanner = new Scanner(System.in);
        int opcao;
            System.out.println("ESCOLHA UMA OPÇÃO:");
            System.out.print("1-Imprime opção escolhida\n0-Sair\nOpção:");
            opcao = scanner.nextInt();
        scanner.close(); //ERRO AQUI. SE REMOVER ESTA LINHA, FUNCIONA.
        return opcao;
    }

    public static void main (String[] args) {

        int opcao;
        Exercicio exercicio = new Exercicio();

        do {
            opcao = exercicio.menu();

            switch (opcao) {                

                case 0 : 
                break;

                case 1 : 
                    System.out.println("Você escolheu a opção 1.\n");
                break;

            }
        }while (opcao != 0);
    }
}

imagem

1 answer

3


This happens because, when closing the Scanner, you also close the object it encapsulates. In the case, you end up closing the System.in.

Only that the System.in is a "special" resource, managed by JVM, and once closed, it cannot be reopened.

So what happens is:

  • you call the method menu, that creates the Scanner, reads the option and closes the Scanner (and consequently closes the System.in).
  • the second time you call the method menu (because it is inside a loop), you create again the Scanner, passing the System.in (which is now closed)
  • when trying to read the data, gives error because the System.in is closed

The solution is not to close the System.in inside the loop. You could create the Scanner outside the loop and pass it to the method menu, for example. And using a block Try-with-Resources, nor need to call close(), for this is automatically called to the end:

// agora recebe o Scanner, em vez de criar toda hora
public int menu(Scanner scanner) {
    int opcao;
    System.out.println("ESCOLHA UMA OPÇÃO:");
    System.out.print("1-Imprime opção escolhida\n0-Sair\nOpção:");
    opcao = scanner.nextInt();
    return opcao;
}

// dentro do main
int opcao;
Exercicio exercicio = new Exercicio();
try (Scanner scanner = new Scanner(System.in)) {
    do {
        opcao = exercicio.menu(scanner);
        switch (opcao) {
            case 0:
                break;
            case 1:
                System.out.println("Você escolheu a opção 1.\n");
                break;
        }
    } while (opcao != 0);
} catch (Exception e) {
    // tratar os erros
}

About the fact you need to close System.in or not, I speak in more detail here.


The syntax Try-with-Resources is available from Java 7. For earlier versions, just do:

int opcao;
Scanner scanner = null;
try {
    scanner = new Scanner(System.in);
    do {
        opcao = menu(scanner);
        switch (opcao) {
            case 0:
                break;
            case 1:
                System.out.println("Você escolheu a opção 1.\n");
                break;
        }
    } while (opcao != 0);
} catch (Exception e) {
    // tratar os erros
} finally {
    if (scanner != null) {
        scanner.close();
    }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.