【问题标题】:How is a string represented in Java internally?Java 内部如何表示字符串?
【发布时间】:2011-12-16 02:12:59
【问题描述】:

我知道 C 字符串 abc 在 C 中内部会是 abc\0,Java 也是这样吗?

【问题讨论】:

    标签: java string


    【解决方案1】:

    不,在 Java 中不一样。没有空终止符。 Java 字符串是对象,而不是指向字符数组。它与 Unicode 字符一起保持长度,因此无需寻找空终止符。

    您不必在这里询问:查看 JDK 附带的 src.zip 中的 String.java 的源代码。这是它的开始:

    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence
    {
        /** The value is used for character storage. */
        private final char value[];
    
        /** The offset is the first index of the storage that is used. */
        private final int offset;
    
        /** The count is the number of characters in the String. */
        private final int count;
    
        /** Cache the hash code for the string */
        private int hash; // Default to 0
    
        /** use serialVersionUID from JDK 1.0.2 for interoperability */
        private static final long serialVersionUID = -6849794470754667710L;
    }
    

    【讨论】:

    • 应该注意的是,value[] 使用了 UTF-16(或它的一个很小的变体?)。并非所有 Unicode 字符都可以填充到单个 char
    • 另外,仅仅因为有一个value[](和一个length并不意味着没有额外的空终止符(好吧,没有' t 在规范的 JVM 中)。例如,BCL -- aka .NET/C# -- has both,尽管终结符从不直接暴露给托管代码。 (另一方面,正因为如此,BCL 不能像 Java 中的 String.substring 那样创建一个字符串到另一个字符串的“视图”。)
    • 我以为问题是关于 Java 的。这与 C# 有什么关系?
    【解决方案2】:

    不,C 字符串是一个字符数组,因此没有与它们关联的长度。这个决定的副作用是,要确定字符串的长度,必须遍历它以找到 \0,这在携带长度方面效率不高。

    Java 字符串有一个 char 数组作为它们的字符,并带有一个偏移长度和一个字符串长度。这意味着确定字符串的长度是相当有效的。

    Source.

    【讨论】:

    • @buruzaemon:你知道连字符也应该找个地方坐,对吧?
    • +1 表示您对chars 的人性化看法以及他们可以休息一会儿的地方,@alex
    • @buruzaemon: Java string != C string
    • 非常感谢您的回答!但是顺便说一句,我正在查看源页面,其中一张显示了程序中创建的字符串的所有内部结构,那个 IDE 是什么?
    • @Will:看起来像 IntelliJ IDEA 中的调试器。
    【解决方案3】:

    C 语言中的字符串是一个 char 类型的数组,而在 Java 中它是一个类,它表示 unicode chars 的集合。

    【讨论】:

      【解决方案4】:

      没有。在 C 中使用空终止符是因为它比传递指针和大小更容易。在 Java 中,大小始终是已知的,因此不需要空终止符。此外,Java 中没有终止字符(输入 \0 将是文字字符串的一部分)。

      【讨论】:

        【解决方案5】:

        Java 字符串不像 C 字符串那样以空值结尾。这是因为 Java 存储字符串的长度。您可以使用String.length() 检索长度。

        【讨论】:

          【解决方案6】:

          String 类是用 Java 实现的。有关示例,请参见 OpenJDK 的 implementation

          OpenJDK 7 String 类带有一个 char[] 类型的数组来保存字符串本身,以及一个偏移量(告诉char[] 中第一个使用的位置)、字符串的长度和字符串的哈希码。

          它还有两个静态字段,一个用于序列化目的的版本 ID 和一个 ObjectStreamField[],这是由于序列化输出流的特殊大小写(至少在 OpenJDK 7 中)。

          【讨论】:

          • ObjectStreamField[] serialPersistentFields 字段是 staticString 不“包含”一个。 serialVersionUID 字段相同。实际上,String 实例有 4 个字段。
          • 我认为 offset 字段在 JDK7 之前被放弃了,可能是因为实现者看到如果 million 是一个百万字符的字符串,让 million.substr(10,3) 持有对百万字符后备存储的引用可以会很浪费。恕我直言,他们应该设计substr 在使用不到一半的旧存储时创建一个新的后备存储,否则在旧存储中进行偏移。这会将最坏情况下的内存使用限制为最佳情况的 2 倍,同时促进一些常用的使用模式。
          【解决方案7】:

          据我所知,在java中String作为对象存储在堆部分作为Object的子类。无需使用 '\0' 来指定字符或字符串。

          【讨论】:

            猜你喜欢
            • 2016-05-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-10-05
            • 2015-08-09
            • 2011-04-16
            • 1970-01-01
            • 2015-03-02
            相关资源
            最近更新 更多