Использование try-with-resources с System.in [дубликат]

Dec 12 2020

Итак, моя IDE жалуется, если я не включу сканер в блок try with, но если я сделаю это таким образом, вместо того, чтобы закрыть его, когда он должен был закрыться (однажды win = true), он закрывает поток System.in, как мне предотвратить это?

public final void turn() {
    System.out.println("Enter your next move!");
    try (Scanner keyboard = new Scanner(System.in)) {
        final String move = keyboard.nextLine();
        if (move.isEmpty()) {
            won = true;
            return;
        }
        if (!validateFormat(move)) {
            System.out.println("Invalid format, try again.");
            return;
        }
        String[] moveAr;
        try {
            moveAr = move.split(",");
        } catch (PatternSyntaxException e) {
            System.out.println(e.getMessage());
            return;
        }
        try {
            validFields(moveAr);
        } catch (InvalidTurnException e) {
            System.out.println(e.getMessage());
            return;
        }
        final char colour = spielFeld.getField(getColumn(moveAr[0].charAt(0)),Character.getNumericValue(moveAr[0].charAt(1)) - 1).getColour();
        for (final String string : moveAr) {
            final int line = Character.getNumericValue(string.charAt(1)) - 1;
            final int column = getColumn(string.charAt(0));
            spielFeld.cross(column,line);
            final int columni = getColumn(string.charAt(0));
            if (spielFeld.columnCrossed(columni)) {
                points += crossedValues(string.charAt(0));
            }
        }
        if (spielFeld.colourComplete(colour)) {
            points += COLOUR_POINTS;
            coloursCrossed++;
        }
        if (coloursCrossed >= 2) {
            won = true;
        }
    }
    System.out.println("Momentane Punkte: " + points);
}

Ответы

a.deshpande012 Dec 12 2020 at 03:19

Я бы рекомендовал не использовать несколько Scannerобъектов, обертывающих один и тот же входной поток. (в данном случае System.in) Причина в том, что сканеры могут потреблять и буферизовать данные из базового потока. Это означает, что в некоторых случаях данные могут быть потеряны. Вы можете прочитать об этом подробнее в этом вопросе .

Здесь вам может сойти с рук, и в этом случае вам просто не следует закрывать объект Scanner, не помещая его в try-with-resources. В этом случае вы можете подавить предупреждение с помощью @SuppressWarnings("resource"). Однако это плохая практика.

Вместо этого я бы рекомендовал создать один глобальный Scannerобъект, который обтекает его System.in, а затем передать его этому методу в качестве параметра вместо создания нового сканера в каждом методе, требующем ввода.

Andreas Dec 12 2020 at 03:16

как мне предотвратить это?

Не закрывайте Scannerобъект, то есть не используйте try-with-resources для Scannerупаковываемого объекта System.in.

Вместо этого примите предупреждение и скройте его, поскольку это особое исключение из обычных правил "ресурсов":

@SuppressWarnings("resource")
Scanner keyboard = new Scanner(System.in);

К вашему сведению: я использую Eclipse IDE, и «Окружить с помощью try-with-resources» - это только первый вариант для устранения предупреждения: