Вот выдержка из документации java.text.CharacterIterator
:
Этот интерфейс
определяет протокол для двунаправленной итерации по тексту. Итератор перебирает ограниченную последовательность символов. [...] Методы
previous ()
иnext ()
используются для итерации. Они возвращаютDONE
if [...], сигнализируя, что итератор достиг конца последовательности.
static final char DONE
: Константа, которая возвращается, когда итератор достиг либо конец или начало текста. Это значение\ uFFFF
, значение «не символ» , которое не должно встречаться ни в одной допустимой строке Unicode .
Курсивом является то, что у меня возникают проблемы с пониманием, потому что из моих тестов, выбросить
и IllegalArgumentException
, если фактически \ uFFFF
запрещено в допустимых строках Unicode?
\ uFFFF
? String
содержать \ uFFFF
в любом случае ? EDIT (2013-12-17): Peter O. приводит отличный аргумент ниже, который делает этот ответ неверным. Старый ответ ниже, для исторической точности.
Ответы на ваши вопросы:
Нет. U+FFFF - это так называемый несимвол. Из Раздела 16.7 Стандарта Юникода:
Несимволы - это кодовые точки, которые постоянно зарезервированы в Стандарте Юникода для внутреннего использования. Они запрещены для использования в открытом обмене текстовыми данными Юникода.
...
В стандарте Юникод зарезервировано 66 несимвольных кодовых точек. Последние две кодовые точки каждой плоскости являются несимвольными: U+FFFE и U+FFFF на BMP, U+1FFFE и U+1FFFF на плоскости 1, и так далее, вплоть до U+10FFFE и U+10FFFF на плоскости 16, всего 34 кодовые точки. точек. Кроме того, существует непрерывный диапазон из еще 32 несимвольных кодовых точек в BMP: U+FDD0...U+FDEF.
Не совсем. Приложениям разрешено использовать эти кодовые точки внутри любым способом. Снова цитирую стандарт:
Приложения могут свободно использовать любые из этих несимвольных кодовых точек внутри, но должны никогда не пытаться обмениваться ими. Если несимвольный код получен в открытом обмене, то приложение не обязано интерпретировать его каким-либо образом. Однако хорошей практикой является распознавание его как несимвола и принятие соответствующих мер, например, замена его на U+FFFD REPLACEMENT CHARACTER, чтобы указать на проблему в тексте. Не рекомендуется просто удалять несимвольные кодовые точки из такого текста из-за потенциальных проблем безопасности, вызванных удалением неинтерпретируемых символов. из-за потенциальных проблем безопасности, вызванных удалением неинтерпретированных символов.
Поэтому, хотя вы никогда не должны встретить такую строку от пользователя, другого приложения или файла, вы вполне можете поместить ее в строку Java, если знаете, что делаете (это означает, что вы не можете использовать CharacterIterator для этой строки, однако.
Как было сказано выше, любая строка, используемая для обмена не должна содержать их. В пределах вашего приложения вы вольны использовать их в любом виде.
Конечно, Java char
, будучи просто 16-битным беззнаковым целым числом, не очень заботится о значении, которое оно содержит.
Нет. На самом деле, раздел о несимволах даже предлагает использовать U+FFFF в качестве дозорного значения:
По сути, несимволы можно рассматривать как внутренние кодовые точки частного использования приложения. В отличие от символов частного использования, обсуждаемых в Разделе 16.5, Символы частного использования, которые назначаются символы и предназначены для использования в открытом обмене, подлежащем интерпретации по частному соглашению, несимволы постоянно зарезервированы (не назначены) и не имеют никакого толкования за пределами их возможного применения - внутреннего частного использования.
U+FFFF и U+10FFFF. Эти две несимвольные кодовые точки имеют свойство связаны с наибольшими значениями кодовых единиц для определенных форм кодирования Юникод. В UTF-16, U+FFFF ассоциируется с наибольшим 16-битным значением кодовой единицы, FFFF16. U+10FFFF ассоциируется с наибольшим легальным значением 32-битной кодовой единицы UTF-32, 10FFFF16. Этот атрибут делает эти две несимвольные кодовые точки полезными для внутренних целей в качестве дозорных. Например, например, они могут использоваться для обозначения конца списка, для представления значения в индексе гарантированно выше любого допустимого символьного значения, и так далее.
CharacterIterator следует этому, возвращая U+FFFF, когда больше нет символов. Конечно, это означает, что если у вас есть другое применение для этой кодовой точки в вашем приложении, вы можете рассмотреть возможность использования другого несимвола для этой цели, поскольку U+FFFF уже занят - по крайней мере, если вы используете CharacterIterator.
Да, использование CharacterIterator значения 0xFFFF в качестве значения DONE является небольшой аномалией. Но все это имеет смысл с точки зрения эффективной обработки текста.
Класс String не запрещает «несимвольные» 0xFFFF и другие зарезервированные или несопоставленные кодовые точки Unicode. Для этого конструкторы String должны будут проверять каждое предоставленное значение char
. Это также вызовет проблемы с обработкой текста, содержащего кодовые точки Unicode, определенные в будущей (относительно JVM) версии Unicode.
С другой стороны, интерфейс CharacterIterator спроектирован так, чтобы разрешить итерацию путем вызова одного простого метода; то есть next ()
. Они решили использовать выделенное значение char
, чтобы указать «больше нет», потому что другие альтернативы:
int
как возвращаемый тип, более сложный для вызывающего. Если CharacterIterator используется для «настоящего» текста Unicode, то тот факт, что вы не можете включить 0xFFFF, не является проблемой. Допустимый текст Unicode не содержит этой кодовой точки. (Фактически, причина того, что 0xFFFF зарезервировано как несимвольное, состоит в поддержке приложений, в которых текст Unicode представлен как строки, оканчивающиеся несимвольным значением. Использование 0xFFFF в качестве символа полностью нарушит это.)
Итог:
String
и Является ли реализация StringCharacterIterator "сломанной", потому что она, например, не выбрасывает IllegalArgumentException, если на самом деле \uFFFF запрещено в допустимых строках Unicode?
Не строго в соответствии с Unicode, но она не согласуется с остальными интерфейсами обработки строк Java, и это несоответствие может иметь очень неприятные последствия. Вспомните все дыры в безопасности, которые мы получили в результате обработки строк, которые рассматривают \0
как терминатор.
Я бы категорически избегал интерфейса CharacterIterator
.