Многочисленные сканеры 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 появляется ошибка «нет строки найденной».

Я предполагаю, что это происходит потому, что Scanner в методе не был закрыт, а затем снова открыт, когда это необходимо. Это что-то не так с программой, и если да, то как я могу ее исправить?

Обратите внимание, что эта программа не завершена, так как я буду добавлять метод продажи, который продает эти акции. Вот почему я использую цикл while.

Наличие нескольких оберток для любого 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() .

  • Сканер пропускает nextLine () после использования next () или nextFoo ()?
  • Как использовать java.util.Scanner, чтобы правильно читать данные пользователя из System.in и действовать на него?
  • Сканер против StringTokenizer против String.Split
  • Проверка входного сигнала сканера во время цикла
  • Ошибка сканера с nextInt ()
  • Получение пользовательского ввода со сканером
  • Чтение .txt-файла с использованием classа Scanner в Java
  • Как я могу справиться со сканером (java)?
  • Закрыть сканер без закрытия System.in
  • Java: бесконечный цикл с использованием Scanner in.hasNextInt ()
  • Сканер только считывает имя файла и ничего больше
  • Давайте будем гением компьютера.