Многочисленные сканеры Java
У меня есть class, который создает несколько объектов Integer
и помещает их в LinkedList
как показано ниже:
public class Shares implements Queue { protected LinkedList L; public Shares() { L = new LinkedList(); } public boolean add(E price) { System.out.println("How many of these shares would you like?"); Scanner scanInt; scanInt = new Scanner(System.in); Integer noShares = scanInt.nextInt(); for (int i = 0; i < noShares; i++) { L.addLast(price); } scanInt.close(); return true; } }
У меня есть приложение, которое сканирует вход «добавить» из консоли и, если он найден, вызывает метод add
как показано ниже:
public class Application { private static Scanner scan; public static void main(String[] args) { Queue S = new Shares(); scan = new Scanner(System.in); System.out.println("Please type add"); String sentence = scan.nextLine(); while (sentence.equals("quit") == false) { if (sentence.equals("add")) { System.out .println("What price would you like to buy your shares at?"); S.add((Integer) scan.nextInt()); } else System.exit(0); sentence = scan.nextLine(); } } }
Приложение должно позволить пользователю вводить «добавить» столько раз, сколько пожелает, но после появления метода add
появляется ошибка «нет строки найденной».
- Чтение CSV со сканером ()
- Java - Закрывающий сканер и утечка ресурсов
- Как использовать несколько объектов Scanner в System.in?
- Ввод Java String Scanner не дожидается информации, перемещается непосредственно в следующий оператор. Как дождаться информации?
- Читать следующее слово в java
Я предполагаю, что это происходит потому, что Scanner
в методе не был закрыт, а затем снова открыт, когда это необходимо. Это что-то не так с программой, и если да, то как я могу ее исправить?
Обратите внимание, что эта программа не завершена, так как я буду добавлять метод продажи, который продает эти акции. Вот почему я использую цикл while.
- Сканер никогда не закрывается
- Сканер не видит после пробела
- В чем разница между методами next () и nextLine () из classа Scanner?
- Как заставить сканер отбрасывать исключения при вводе неправильного типа?
- Извлечь целочисленную часть в строке
- Использование scanner.nextLine ()
- Сканер против BufferedReader
- Метод сканирования для получения символа
Наличие нескольких оберток для любого streamа – отличный способ по-настоящему смутить себя. Я предлагаю вам только однажды обернуть stream, если вы не знаете, что делаете.
Самый простой способ сделать это – использовать одноэлемент в этом случае, поскольку он обертывает другой синглтон (лучше всего пройти вокруг Сканера в качестве аргумента)
public class Application { // use this Scanner in all you other code, don't create another one. static final Scanner scan = new Scanner(System.in); public static void main(String[] args) {
Я предполагаю, что это потому, что сканер в методе не был закрыт
Когда вы закрываете stream, он закрывает базовый stream, и вы не можете его использовать снова. Только закрыть System.in, если вы хотите, чтобы он не использовался снова.
как я могу это исправить?
Лучшим решением является использование всего вашего сканера в одном месте, одном методе или одном classе. У вас есть основное () все взаимодействие с пользователем и передача значений в структуру данных. Иметь объекты, которые инициализируют себя, – это плохая практика, чтобы войти, и если вы начнете это делать, это поразит вас до конца ваших дней разработки;) (Серьезно вы увидите, что это делается снова и снова, и часто это кошмар)
BTW Никогда не выходите из программы без объяснения причин. Вызов System.exit(0);
даже сообщение об ошибке также не является кошмаром. Я когда-то работал над проектом, который имеет 260 вызовов System.exit () часто без сообщения об ошибке, вы можете себе представить, насколько весело проводить диагностику сервера, просто останавливаясь без видимых причин.
Первая ошибка заключается в том, что эта строка кода
scanInt.close();
закрывает System.in, а не только объект scanInt. Это означает, что после первого вызова для добавления объект проверки будет потреблять только тот вход, который у него уже есть, а затем вы получите исключение NoSuchElementException: удалите эту строку.
Теперь, если вы замените последнюю строку, которую вы имеете с этим
sentence = scan.nextLine(); System.out.println("sentence: \"" + sentence + "\"");
вы увидите, что последний вход, который вы получаете перед выходом, является пустой строкой. Поэтому в следующем цикле вы вводите оператор else, и ваша программа прекращает выполнение. Вы можете устранить эту проблему, добавив следующее:
scan.nextLine(); // consume the first always empty String... System.out.println("Please type add"); sentence = scan.nextLine(); // and then get the actual value
Однако я соглашусь с Питером, что вы не должны использовать несколько оберток. Рассмотрим передачу объекта Scanner в качестве аргумента в подрядчике classа «Акции».
Множество сканеров (в одном streamе) – очень плохая практика, потому что сканеры потребляют stream, который они используют.
Я проверил при отладке исходного кода и просмотрел class Scanner
который я нашел:
- ссылка на входной stream источника
- внутренний закрытый буфер, используемый для хранения ввода.
Поэтому, когда экземпляр сканера потребляет свой stream, в основном он просто читает кучу байтов (1024), и позиция streamа перемещается вперед.
Например, когда метод nextLine()
является invoket, за кулисами source.read()
копирует результат в частный буфер.
Очевидно, состояние другого сканера ухудшается (недействительно).
Попробуйте самостоятельно отлаживать исходный код Java и / или посмотреть на метод Scanner.readInput()
.