Почему неразрывное пространство не является символом пробела в java?

При поиске подходящего способа обрезать неразрывное пространство из разобранного HTML я впервые наткнулся на java spartan definition String.trim(), который, по крайней мере, правильно документирован. Я хотел, чтобы явным образом не перечислял символы, подходящие для обрезки, поэтому я предположил, что использование поддерживаемых Unicode методов в классе Character выполнит эту работу для меня.

Что, когда я обнаружил, что Character.isWhitespace(char) явно исключает неразрывные пробелы:

Это символ пробела Unicode (SPACE_SEPARATOR, LINE_SEPARATOR или PARAGRAPH_SEPARATOR) , но также не является неразрывным пробелом ('\u00A0', '\u2007', '\u202F').

Почему?

Реализация соответствующего эквивалента .NET является менее дискриминационной.

Ответ 1

Character.isWhitespace(char) является старым. Действительно старый. Многие вещи, сделанные в первые дни Java, соответствовали соглашениям и реализациям с C.

Теперь, более десятилетия спустя, эти вещи кажутся ошибочными. Подумайте, как это произошло, даже в первые дни работы Java и первых дней .NET.

Java стремится к 100% обратной совместимости. Поэтому даже если бы команда Java подумала, что было бы неплохо исправить свою первоначальную ошибку и добавить неразрывные пробелы в набор символов, возвращающий true из Character.isWhitespace(char), они не могут, потому что почти наверняка существует программное обеспечение, которое опирается на текущую реализацию, работающую точно так, как она делает.

Ответ 2

Так как Java 5 также существует isSpaceChar(int). Разве это не делает то, что вы хотите?

Определяет, является ли указанный символ (кодовая точка Юникода) символом пробела в Юникоде. Символ считается символом пробела тогда и только тогда, когда он задан как символ пробела по стандарту Unicode. Этот метод возвращает true, если тип общей категории символов является одним из следующих:...

Ответ 3

Как указано выше, isSpaceChar(int) предоставит OP дорожку для ответа. Это выглядит довольно осторожно документированным, но этот метод фактически используется с регулярными выражениями. Итак:

    "X\u00A0X X".replaceAll("\\p{javaSpaceChar}", "_");

создаст строку "X_X_X". В качестве упражнения для читателя остается придумать регулярное выражение, чтобы обрезать строку. (Шаблон с некоторыми флагами должен сделать трюк.)

Ответ 4

Я бы сказал, что реализация Java более корректна, чем .NET. Неразрывное пространство по существу является не-пробельным символом, который выглядит как один. То есть, если у вас есть строки "foo" и "bar", и между ними помещается любой традиционный символ пробела, вы получите слово break. Неразрывное пространство, однако, не разбивает два.

Ответ 5

Единственный раз, когда необратимое пространство должно быть обработано специально, - это код, предназначенный для выполнения текстового переноса текста.

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

Любой аргумент, что неразрывное пространство просто "похоже" на пробел, но не конфликтует со всей точкой Unicode, которая представляет символы на основе их значения, а не как они отображаются.

Таким образом, IMHO, реализация Java String.trim() не выполняется так, как ожидалось, и основная функция Character.isWhitespace() не работает.

Моя догадка заключается в том, что разработчики Java написали isWhitespace() на основе необходимости выполнять перенос текста в элементах управления. Они должны были назвать эту функцию isWordWrappingBoundary() или что-то более понятное и использовали менее ограничивающий пробельный тест для trim().

Ответ 6

Похоже, что имя метода (isWhitespace) не соответствует его функции (для обнаружения разделителей). Функциональность "разделитель" довольно понятна, если вы посмотрите полный список символов со страницы Javadoc, которую вы цитировали:

* It is a Unicode space character (SPACE_SEPARATOR, LINE_SEPARATOR, or PARAGRAPH_SEPARATOR) but is not also a non-breaking space ('\u00A0', '\u2007', '\u202F').
* It is '\u0009', HORIZONTAL TABULATION.
* It is '\u000A', LINE FEED.
* It is '\u000B', VERTICAL TABULATION.
* It is '\u000C', FORM FEED.
* It is '\u000D', CARRIAGE RETURN.
* It is '\u001C', FILE SEPARATOR.
* It is '\u001D', GROUP SEPARATOR.
* It is '\u001E', RECORD SEPARATOR.
* It is '\u001F', UNIT SEPARATOR. 

Неразрывная пространственная функция должна быть визуальным пространством между словами, которые не разделены алгоритмами переноса.

Ответ 7

Также будьте осторожны при использовании функции apache commons StringUtils.isBlank() (и связанных функций), которая имеет тот же странный isWhitespace, то есть неразрывное пространство считается непустым.