2013-09-11 5 views
31

Это действительно любопытство более чем проблема ...Почему класс сканера не имеет метода nextChar?

Почему Scanner класса нет метода nextChar()? Похоже, что это необходимо, если учесть, что он имеет next, nextInt, nextLine и т. Д. Способ.

Я понимаю, что вы можете просто сделать следующее:

userChar = in.next().charAt(0); 
System.out.println(userChar ); 

Но почему нет метода nextChar()?

+3

В качестве временного решения можно попробовать 'следующий ("") '. –

+0

Глядя на источник, кажется, что 'next (". ")' Сначала пропустит разделители (пробелы по умолчанию). Может быть, это то, что нужно. Если нет, вам нужно использовать 'sc.delimiter()' для сохранения текущего шаблона разделителя 'sc.useDelimiter (??)', чтобы установить его на что-то, что не соответствует чему-либо (может быть, пустой шаблон, но Я его не тестировал); _then_ 'next (". ")'; затем 'sc.useDelimiter', чтобы восстановить предыдущий разделитель. – ajb

ответ

14

Причина заключается в том, что класс сканера предназначен для чтения в токенах, разделенных пробелами. Это класс удобства, который обтекает базовый поток ввода. Перед сканером все, что вы могли сделать, было прочитано в байтах, и это большая боль, если вы хотите читать слова или строки. С помощью Scanner вы передаете System.in и выполняет ряд операций read() для токенизации ввода для вас. Чтение одного символа - более простая операция. Source

Вы можете использовать (char) System.in.read();.

3

Согласно javadocScanner, кажется, не быть предназначен для чтения одиночных символов. Вы прикрепляете Scanner к InputStream (или что-то еще), и он анализирует ввод для вас. Он также может вырезать нежелательные символы. Таким образом, вы можете легко читать числа, строки и т. Д. Если вам нужны только символы с вашего ввода, используйте, например, InputStreamReader.

1

Класс сканера основан на логике, реализованной в методе String next(Pattern). Дополнительный API-метод, такой как nextDouble() или nextFloat(). Предоставьте шаблон внутри.

Тогда класс description says:

Простой текстовый сканер, который может анализировать примитивные типы и строки с использованием регулярных выражений.

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

Из описания может быть грустно, что кто-то забыл о char, поскольку он является примитивным типом.

Но понятие класса состоит в том, чтобы найти шаблоны, символ не имеет никакого шаблона, это просто следующий символ. И эта логика ИМХО вызвала то, что nextChar не был реализован.

Если вам нужно прочитать поданный символ char, вы можете использовать более эффективный класс.

1

Я бы предположил, что это связано с кодировкой. A char - 16 байт, а некоторые кодировки будут использовать один байт для символа, тогда как другой будет использовать два или даже больше.Когда Java была изначально разработана, они предположили, что любой символ Юникода будет вписываться в 2 байта, тогда как теперь для символа Unicode может потребоваться до 4 байтов (UTF-32). Нет никакого способа для Scanner представлять кодовую точку UTF-32 в одном char.

При создании экземпляра вы можете указать кодировку Scanner, и если она не указана, она будет использовать набор символов платформы. Но это все еще не справляется с проблемой с символами Unicode с 3 или 4 байтами, поскольку они не могут быть представлены как один примитив char (поскольку char составляет всего 16 байт). Таким образом, вы получите непоследовательные результаты.

+2

Я не понимаю. Если «Сканер» не может получить символы, потому что он не может определить кодировку, как он может реализовать _any_ своих методов сканирования? В конце концов, эти методы должны смотреть на персонажей, нет? – ajb

+0

Вы имели в виду методы, где он возвращает 'String'? Проблема в том, что если у вас есть 4-байтовый символ юникода, как вы представляете это как 'char'? Если это был 'String', он может быть внутренне представлен как массив' char' с двумя 'char' внутри него. Но нет никакого способа получить значимый ответ от 'nextChar', если вы имеете дело с 3 или 4 байтовыми символами юникода. –

+0

Насколько я знаю, «Reader» несет ответственность за обработку кодировки. Посмотрите http://docs.oracle.com/javase/1.5.0/docs/api/index.html? Java/io/InputStream.html –

1

Чтобы получить определенную причину, вам нужно спросить дизайнера (ов) этого API.

Но одна из возможных причин состоит в том, что намерение (гипотетическое) nextChar не очень хорошо вписывается в модель сканирования.

  • Если nextChar() для себя как read() на Reader и просто вернулся на следующий неизрасходованного характер со сканера, то он ведет себя непоследовательно с другими next<Type> методами. Они пропускают символы ограничителя, прежде чем они попытаются проанализировать значение.

  • Если nextChar() для себя, как (скажем) nextInt тогда:

    • разделителем пропуск будет «неожиданным» для некоторых людей, и

    • есть вопрос о том, следует ли принимать один «необработанный» символ или последовательность цифр, которые представляют собой числовое представление char, или, может быть, даже поддерживают экранирование или что-то еще .

Независимо от того, какой выбор они сделали, некоторые люди не будут счастливы. Я предполагаю, что дизайнеры решили держаться подальше от tarpit.


1 - проголосовали бы решительно для необработанного подхода характер ... но дело в том, что есть альтернативы, которые должны быть проанализированы и т.д.

Смежные вопросы