为什么Java中string.indexOf方法的参数是int类型

13
我想知道为什么indexOf方法的参数是int类型,而不是char类型,因为描述中明确写着是char类型。 public int indexOf(int ch)
Returns the index within this string of the first occurrence of the specified **character**

http://download.oracle.com/javase/1,5.0/docs/api/java/lang/String.html#indexOf%28int%29

Also, both of these compiles fine:
char c = 'p';
str.indexOf(2147483647);
str.indexOf(c);

a]在Java中,int是32位的,而Unicode字符是16位的,我感到困惑的是为什么不直接使用字符本身而要使用int。这样做有没有性能优化?用字符表示比int难吗?怎么难?

b]我认为应该有简单的原因,这使我更加想了解它!

谢谢!

4个回答

18
真正的原因是indexOf(int)需要一个Unicode代码点,而不是一个16位UTF-16“字符”。Unicode代码点实际上可以长达21位。
(较长代码点的UTF-16表示实际上由2个16位“字符”值组成。这些值分别称为前导代理项和尾随代理项;D80016到DBFF16,以及DC0016到DFFF16。有关详细信息,请参见Unicode FAQ - UTF-8、UTF-16、UTF-32和BOM。)
如果您给indexOf(int)一个大于65535的代码点,它将搜索编码该代码点的UTF-16“字符”对。
虽然Java文档中并没有明确说明,但是代码的检查表明,这确实是该方法的实现方式。

为什么不只使用16位字符?

很显然,如果他们这样做,就没有一种简单的方法来定位大于65535的代码点。这将是开发国际化应用程序且文本可能包含此类代码点的人们的主要问题。(许多所谓的国际化应用程序做出了错误的假设,即char表示代码点。通常情况下并不重要,但越来越重要。)
但这对您没有任何影响。如果您的字符串只由16位代码或ASCII代码组成,该方法仍将起作用。

谢谢回答。好的,现在我明白了indexOf(int)需要一个Unicode码点,我的另一个问题是为什么?为什么不只使用16位字符呢? - codeObserver
1
因为Unicode字符实际上是22位而不是16位。因此,有一些“字符/字母”(代码点)无法存储在Java字符中。这就是为什么Java字符串可能使用2个字符来存储一个“代码点/字母”的原因(如果您真的想知道,请参见UTF-16代理对)。 - MTilsted

4
Java中的字符以它们的Unicode整数表示存储。 Character类文档详细介绍了这种格式。
从该页面的文档中可以看到:
接受int值的方法支持所有Unicode字符,包括补充字符。例如,Character.isLetter(0x2F81A)返回true,因为代码点值代表一个字母(一个CJK表意文字)。

感谢。文档中有两个语句:int 的低(最不重要的)21 位用于表示 Unicode 代码点,而高(最重要的)11 位必须为零。Unicode 规范将字符定义为固定宽度的 16 位实体。那么,如果 Unicode 是 16 位,为什么要使用 21 位来表示它们? - codeObserver
是的,但在编码下,字符串是一个byte[]数组,使用UTF-8编码。标准字符(0-255)仅占用一个字节(不像全角字符占用两个字节)。超过255的字符需要多个字节,有时需要超过2个字节。编码后的字符具有一个整数(32位)等效值——这就是indexOf()搜索的内容。 - Bohemian
@p1 很长时间以来,Unicode 就不再是 16 位了。Unicode 2.0 解除了这个限制,而那已经是 15 年前的事情了(我感觉自己老了)。从技术上讲,ISO-10646 是一个 31 位地址空间,而 Unicode 理论上可以表示其中任何一个。实际上,UTF-16 仅限于 21 位,而 Unicode 实际上已经承诺只支持这 21 位。ISO-10646 几乎不可能以一种会破坏 UTF-16 的方式失步于 Unicode,因此 21 位现在有效地成为硬编码限制。 - Cowan
1
@Bohemian - 您关于String在底层是byte[]的评论是不正确的。正常的内存表示使用char[]...而不是UTF-8。 - Stephen C
@StephenC 我那时候比较蠢 :/ - 发个点赞给你,因为你翻找 评论 找到这个(你一定是有超能力或者很执着 :) ) - Bohemian
@Bohemian - 我在我的答案上看到了一些“活动”,并注意到了你的评论。 - Stephen C

0

方法str.indexOf(int)需要一个整数。如果您将一个char传递给它,Java会将char强制转换为int,因为char是一个16位数字。


0

Java在幕后执行了一整套隐式类型转换规则。对于原始类型,有特殊的规则,这些规则都在Sun的Java文档中Conversions and Promotions中详细说明。对于您的具体问题,将int转换为char是一种“缩小原始类型转换”。请参阅上述文档中的第5.1.3节。

话虽如此,将编码为整数的小正整数和字符互换是一种常见的编程实践。这可以追溯到它们在C语言中不可区分的使用,当时只有ASCII存在。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接