Java中字符串是如何内部表示的?

6

我知道在C语言中,一个字符串abc的内部表示为abc\0,那么在Java中是否也是这种情况呢?

7个回答

11
不,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;
}

需要注意的是,UTF-16被用于value[](或者是它的一个非常微小的变体?)。并不是所有的Unicode字符都能够被塞进一个单独的char中。 - user166390
此外,仅仅因为有value [](和length)并不意味着没有额外的空终止符(好吧,在规范的JVM中没有)。例如,BCL-又称.NET/C#-两者都有,尽管终止符从未直接暴露给托管代码。(另一方面,由于这个原因,BCL不能像Java的String.substring那样创建一个字符串的“视图”进入另一个字符串。) - user166390
我原本以为这个问题是关于Java的。这跟C#有什么关系? - duffymo

8
不对,C字符串是由字符数组组成的,因此它们没有与之关联的长度。这种决策的副作用是要确定字符串的长度,必须通过迭代来查找\0,这不如携带长度高效。
Java字符串具有用于其字符的char数组,并携带偏移长度和字符串长度。这意味着确定字符串的长度相当高效。 来源

4
你知道连字符也应该有自己的位置,对吧? - alex
1
+1 对于你对 char 类型的人道观点以及它们可以暂时歇息的地方,@alex 表示赞同。 - buruzaemon
1
@buruzaemon: Java字符串 != C字符串 - alex
这太棒了,谢谢你的回答!顺便说一下,我正在查看源页面,其中有一张图片显示程序中创建的字符串的所有内部信息,那是什么IDE? - Will
@Will:看起来是在 IntelliJ IDEA 中的调试器。 - reve_etrange

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

2

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


2

Java字符串与C字符串不同,它们不以null结尾。这是因为Java存储了字符串的长度。您可以使用String.length()方法检索字符串的长度。


1

Java中实现了String类。请参见OpenJDK的实现以获取示例。

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

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


ObjectStreamField[] serialPersistentFields 字段是一个 static 字段。一个 String 不会“包含”它。serialVersionUID 字段同样如此。实际上,一个 String 实例有 4 个字段。 - Stephen C
我认为在JDK7之前,偏移字段被废弃了,可能是因为实现者们意识到,如果million是一个百万字符的字符串,让million.substr(10,3)持有对百万字符后备存储的引用可能会非常浪费。依我看来,他们应该设计substr在使用旧存储的一半以下时创建新的后备存储,否则使用旧存储的偏移量。这样可以将最坏情况下的内存使用限制在最优解的两倍,同时方便一些常见的有帮助的使用模式。 - supercat

0
据我所知,在Java中,String作为Object的子类以对象的形式存储在堆内存中。因此,没有必要使用'\0'来指定字符或字符串。

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