У меня есть Scanner
, связанный с System.in
. Теперь, после использования Scanner
, я должен закрыть его, так как оставлять его открытым — плохая практика кодирования. Но если я закрою Scanner
, я также закрою System.in
! Может ли кто-нибудь сказать мне, как я могу закрыть Scanner
, не закрывая System.in
(если есть какой-либо способ).
Закройте сканер, связанный с System.in
Ответы (5)
Один из вариантов — обернуть поток System.in
в поток CloseShieldInputStream
, который предотвратит его закрытие. Тогда ваш читатель будет использовать поток CloseShieldInputStream
, а не необработанный поток System.in
.
Вот API для класса: http://commons.apache.org/io/apidocs/org/apache/commons/io/input/CloseShieldInputStream.html
Самое простое — не закрывать Scanner, если вы не хотите закрывать основной поток.
В идеале вы должны создать только один сканер, который вы будете использовать на протяжении всей жизни программы. В любом случае, похоже, у вас нет веских причин закрывать его.
CloseShieldInputStream
позволяет коду игнорировать этот факт и просто обрабатывать его как любой другой InputStream и пытаться закрыть его по завершении. То, что здесь просто, на самом деле зависит от контекста.
- person candied_orange; 26.11.2016
Вместо того, чтобы добавлять классы щитов и тому подобное, просто оставьте хороший комментарий и
@SuppressWarnings("resource")
Этого достаточно. И я не вижу много недостатков в этом подходе. Не забудьте комментарий.
IOException: Stream closed
при попытке использовать System.in
после закрытия сканера.
- person derHugo; 14.12.2018
У меня есть смутные воспоминания о странных, не поддающихся диагностике проблемах, связанных с использованием одного и того же Scanner
из System.in
дважды, поэтому я использую это (хотя вам, вероятно, следует использовать только один сканер на время программы):
static String input() {
try {
return new Scanner(System.in).nextLine();
} catch (NoSuchElementException e) {
throw e;
}
}
По какой-то причине это работает без предупреждений, тогда как если я не сделаю ловушку, Eclipse будет жаловаться Resource leak: '<unassigned Closeable value>' is never closed
.
Согласно API для InputSteam «Метод close для InputStream ничего не делает», поэтому, поскольку System.in является экземпляром InputStream, вам не нужно беспокоиться о том, что для него будет вызван метод close().
Scanner
на System.in
, закрою его, а затем открою другой и попытаюсь использовать его (например, nextLine()
), я получу NoSuchElementException
.
- person Blrp; 06.11.2015
close()
действительно ничего не делает в стандартной реализации абстрактного InputStream
, это не означает, что это верно для всех его подклассов! Если бы это было правдой, метод был бы бесполезен.
- person Jiri Tousek; 08.01.2016
InputStream
— это абстрактный класс. Подклассы могут и должны что-то делать, когда они представляют ресурс (например, стандартный ввод), который необходимо закрыть после использования. Конечно, это можно было бы прояснить в InputStream.close()
, но ваш вывод неверен.
- person dimo414; 26.02.2016
System.in
являетсяInputStream
и поэтому реализуетAutoClosable
, см. документы. - person jlordo   schedule 03.01.2013