我知道在C语言中,一个字符串abc
的内部表示为abc\0
,那么在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;
}
\0
,这不如携带长度高效。在C语言中使用空终止符是因为这比传递指针和大小更容易。在Java中,大小总是已知的,因此不需要空终止符。此外,在Java中没有终止字符(放入\0
将成为文本字符串的一部分)。
Java字符串与C字符串不同,它们不以null结尾。这是因为Java存储了字符串的长度。您可以使用String.length()
方法检索字符串的长度。
Java中实现了String
类。请参见OpenJDK的实现以获取示例。
OpenJDK 7 String
类携带一个char[]
类型的数组来保存字符串本身,以及偏移量(告诉char[]
中第一个使用的位置)、字符串长度和字符串的哈希码。
它还有两个静态字段,一个版本ID用于序列化目的,另一个是ObjectStreamField[]
,由于与序列化输出流的特殊情况有关(至少在OpenJDK 7中)。
ObjectStreamField[] serialPersistentFields
字段是一个 static
字段。一个 String
不会“包含”它。serialVersionUID
字段同样如此。实际上,一个 String
实例有 4 个字段。 - Stephen Cmillion
是一个百万字符的字符串,让million.substr(10,3)
持有对百万字符后备存储的引用可能会非常浪费。依我看来,他们应该设计substr
在使用旧存储的一半以下时创建新的后备存储,否则使用旧存储的偏移量。这样可以将最坏情况下的内存使用限制在最优解的两倍,同时方便一些常见的有帮助的使用模式。 - supercat
value[]
(或者是它的一个非常微小的变体?)。并不是所有的Unicode字符都能够被塞进一个单独的char
中。 - user166390value []
(和length
)并不意味着没有额外的空终止符(好吧,在规范的JVM中没有)。例如,BCL-又称.NET/C#-两者都有,尽管终止符从未直接暴露给托管代码。(另一方面,由于这个原因,BCL不能像Java的String.substring
那样创建一个字符串的“视图”进入另一个字符串。) - user166390