假设在此时,您具体谈论的是
Reader.read()
方法,那么您所转述的“某人”的说法实际上是
不正确的。确实有一些Unicode代码点的值大于65535,因此不能表示为单个Java
char
。但是,
Reader
API实际上产生一系列Java
char
值(或-1),而不是一系列Unicode代码点。这在
javadoc中明确说明。
如果您输入的内容包含一个(适当编码的) Unicode 码点,大于 65535,那么您需要调用两次 `read()` 方法才能看到它。您将得到一个 UTF-16 代理对;即两个 Java `char` 值,它们 `一起` 表示该码点。事实上,这符合 Java String、StringBuilder 和 StringBuffer 类的工作方式;它们都使用基于 UTF-16 的表示形式...带有嵌入的代理对。
`Reader.read()` 返回 `int` 而不是 `char` 的真正原因是允许它返回 `-1`,以表示没有更多的字符可读取。同样的逻辑解释了为什么 `InputStream.read()` 返回 `int` 而不是 `byte`。
假设Java的设计者们可能会规定
read()
方法抛出异常来表示“流结束”的条件。然而,这只是用另一种方式取代了一个潜在的错误源(未测试结果),而变成了另一个错误源(未处理异常)。此外,异常相对比较耗费资源,而流结束并不是真正意义上的意外/异常事件。总之,在我看来,当前的方法更好。
(另一个关于
Reader
API 16位特性的线索是
read(char[]...)
方法的签名。如果没有使用代理对,它如何处理大于65535的码点?)
编辑:
DataOutputStream.writeChar(int)
似乎有点奇怪。但是,javadoc清楚地说明了参数将作为2字节值写入。实际上,实现只将底部两个字节写入底层流中。
我认为没有一个好的理由来解释这个问题。无论如何,有一个与此相关的错误数据库条目(
4957024),标记为“11-已关闭,不是缺陷”,并附有以下评论:
“这不是一个很好的设计或借口,但它太深入了,我们不能改变。”
这在某种程度上承认了这确实是一个缺陷,至少从设计角度来看。
但是,在我看来,这不值得大惊小怪。
char
相关的方法,因为它们用于二进制数据;文本数据需要适当的编码,而流本身不应该知道。 - Jon Skeet