为什么 Java 无法识别这些空格?

Why does Java not recognize these white spaces?

25 types of white spaces个。下面代码中的 Character.isWhitespace(char) 表明 25 种类型中有四种在 Java 中不被视为白色 space。为什么?

public class Main {
    public static void main(String...args){
        char [] whiteSpaces = {'\u0085', '\u00A0', '\u2007', '\u202F'};
        for(char space : whiteSpaces){
            //All spaces are not white spaces in Java.
            System.out.println("[" + space + "] is a white space in Java:" + Character.isWhitespace(space));
        }
    }
}

参考-https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Character.html#isWhitespace(char)

为什么?因为那是指定该方法的方式。 javadoc for isWhiteSpace 列出了它匹配的代码。您确定的 4 个不在列表中。

我们无法告诉您为什么这样定义它。但是,javadoc 所说的一个含义是 '\u00A0''\u2007''\u202F' 被排除在外,因为它们是 non-breaking 白色 space 字符。

'\u0085'NEL 是一个有趣的案例。根据 Unicode 代码表(参见 here 的非官方摘要),它不是一般类别 SPACE_SEPARATOR、LINE_SEPARATOR 或 PARAGRAPH_SEPARATOR 的成员。 (它显示在“控制”类别中。)

如果您想要一种识别所有 Unicode 白色 space 字符(即 SPACE_SEPARATOR、LINE_SEPARATOR 或 PARAGRAPH_SEPARATOR 中的字符)的方法,您应该使用 isSpaceChar (javadoc) 而不是 isWhiteSpace.

请注意,Unicode 规范不是一成不变的。代码的分类,以及“白色 space”的定义确实随着时间的推移而演变。每个 Java version implements a specific version of the Unicode spec 在发布时都是最新的。例如:

  • Java 8 实现 Unicode 6.2
  • Java 11 实施 Unicode 10.0.0
  • Java 13 实现 Unicode 12.1

每个 Java 版本的 Character class 的 javadoc 中有详细信息。请注意,给定的 Java 版本未修补以跟踪后续的 Unicode 版本。


最重要的是,“白色 space”是一个相当狡猾的概念。如果你想要一个实现特定含义的方法,你可能需要自己实现。

Java 似乎没有在任何地方公开 unicode whitespace 列表

在Java中,isWhitespace具体定义为以下之一:

  • 它是一个 Unicode space 字符(SPACE_SEPARATOR、LINE_SEPARATOR 或 PARAGRAPH_SEPARATOR)但不是 non-breaking space ('\u00A0', '\u2007', '\u202F').
  • 是'\t',U+0009 水平制表。
  • 是'\n', U+000A LINE FEED.
  • 是'\u000B',U+000B 竖排表。
  • 是'\f', U+000C FORM FEED.
  • 是'\r', U+000D CARRIAGE RETURN.
  • 它是'\u001C',U+001C 文件分隔符。
  • 它是'\u001D',U+001D 组分隔符。
  • 是'\u001E', U+001E RECORD SEPARATOR.
  • 它是'\u001F', U+001F 单位分隔符。

Java 也使 unicode spaces 可用,但不是 unicode whitespaces,通过 Character.isSpaceChar()。这是一个略有不同的列表。

char [] whiteSpaces = {'\u0085', '\u00A0', '\u2007', '\u202F'};
        for(char space : whiteSpaces){
            //All spaces are not white spaces in Java.
            System.out.println("[" + space + "] is a white space in Java: " + Character.isWhitespace(space) + " Unicode: " + Character.isSpaceChar(space));
        }

输出:

[] is a white space in Java: false Unicode: false
[ ] is a white space in Java: false Unicode: true
[ ] is a white space in Java: false Unicode: true
[ ] is a white space in Java: false Unicode: true

如果您的应用程序匹配 unicode 规范而不是 java 规范很重要,请自行定义。

如果您阅读文档,即 Character.isWhitespace(char) 的 javadoc,它说:

Determines if the specified character is white space according to Java. A character is a Java whitespace character if and only if it satisfies one of the following criteria:

  • 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 '\t', U+0009 HORIZONTAL TABULATION.
  • It is '\n', U+000A LINE FEED.
  • It is '\u000B', U+000B VERTICAL TABULATION.
  • It is '\f', U+000C FORM FEED.
  • It is '\r', U+000D CARRIAGE RETURN.
  • It is '\u001C', U+001C FILE SEPARATOR.
  • It is '\u001D', U+001D GROUP SEPARATOR.
  • It is '\u001E', U+001E RECORD SEPARATOR.
  • It is '\u001F', U+001F UNIT SEPARATOR.

您列出的 4 个中有 3 个被明确排除,因为它们是 non-breaking spaces.

至于U+0085 NEXT LINE (NEL),它不是Unicode space字符,Java也不认为它是白色space字符,你可以看到在那个javadoc中。