【问题标题】:Why is parameter to string.indexOf method is an int in Java为什么 string.indexOf 方法的参数是 Java 中的 int
【发布时间】:2011-06-02 04:04:52
【问题描述】:

我想知道为什么 indexOf 方法的参数是 int ,而描述是 char。

公共 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 是 32bit ,而 unicode 字符是 16 bits 。

b]为什么不使用字符本身而不是使用 int 。这是任何性能优化吗? chars 比 int 更难表示吗?怎么样?

我认为这应该是一个简单的推理,这让我更加了解它!

谢谢!

【问题讨论】:

    标签: java data-structures primitive-types


    【解决方案1】:

    真正的原因是 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,它将搜索编码该代码点的 pair UTF-16 字符。

    javadoc 中说明了这一点(虽然不是很清楚),并且对代码的检查表明这确实是该方法的实现方式。


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

    这很明显。如果他们这样做了,就不会有一种简单的方法来定位字符串中大于 65535 的代码点。对于开发文本可能包含此类代码点的国际化应用程序的人来说,这将是一个主要问题。 (许多所谓的国际化应用程序错误地假设 char 代表一个代码点。通常这无关紧要,但越来越常见。)

    但它不应该对你有任何影响。如果您的字符串仅包含 16 位代码......或者就此而言,仅包含 ASCII 代码,则该方法仍然有效。

    【讨论】:

    • 谢谢你的答案。好的,所以现在我看到 indexOf(int) 需要一个 Unicode 代码点,我的另一个问题是.. 为什么会这样? .为什么不只使用 16 位字符?
    • 因为 unicode 字符实际上是 22 位,而不是 16 位。所以有些“字符/字母”(代码点)不能存储在 java char 中。这就是为什么 Java 字符串可能使用 2 个字符来存储一个“代码点/字母”(如果您真的想知道,请参阅 utf-16 代理对)。
    【解决方案2】:

    Java 中的字符以它们的 unicode 整数表示形式存储。 Character 类文档有更多关于这种格式的详细信息。

    来自该页面上的文档:

    接受 int 值的方法支持所有 Unicode 字符,包括补充字符。例如,Character.isLetter(0x2F81A) 返回 true,因为代码点值表示一个字母(CJK 表意文字)。

    【讨论】:

    • 谢谢。文档中的 2 条语句:int 的低(最低有效)21 位用于表示 Unicode 代码点,高(最高)11 位必须为零。 Unicode 规范,将字符定义为固定宽度的 16 位实体 那么如果 unicode 是 16 位,为什么要用 21 位来表示呢?
    • 是的,但是字符串是字节[],编码为 UTF-8。标准字符 (0-255) 只占用一个字节(不是全角字符占用的两个字节)。超过 255 个字符占用多个字节,有时超过 2 个字节。编码字符有一个等价的整数(32 位)——这就是 indexOf() 搜索的内容
    • @p1 Unicode 很久没有成为 16 位了。 Unicode 2.0 取消了 16 位的限制,那是 15 年前的事了(我觉得老了)。从技术上讲,ISO-10646 是一个 31 位地址空间,而 Unicode 理论上可以代表其中的任何一个。实际上,UTF-16 仅限于 21 位,而 Unicode 已有效地承诺仅支持这 21 位。极不可能允许 ISO-10646 与 Unicode 不同步而破坏 UTF-16,因此 21 位现在实际上是硬编码限制。
    • @Bohemian - 您关于 String 在幕后是 byte[] 的评论不正确。正常的内存表示使用char[] ...而不是UTF-8。
    • @StephenC 那时我比较笨:/ - 为你在 comment 中找到这个问题投了赞成票(你一定是通灵者或痴迷者 :))
    【解决方案3】:

    str.indexOf(int) 方法采用 int。如果您将char 传递给它,java 会将char 转换为int,因为char 是一个16 位数字。

    【讨论】:

      【解决方案4】:

      Java 在后台执行了大量隐式类型转换规则。对于原语,有一些特殊的规则,所有这些都在文档Conversions and Promotions 中进行了概述,该文档是 Sun 的 Java 文档的一部分。对于您的具体问题,将 int 转换为 char 是“缩小原始转换”。请参阅上述文档中的第 5.1.3 节。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-30
        • 1970-01-01
        • 1970-01-01
        • 2012-06-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-11
        相关资源
        最近更新 更多