字符串是不可变的,因为它们存储在常量字符串池中 . 那么,stringbuilder对象在哪里创建?说,我创建了两个字符串构建器对象
StringBuilder s1 = new StringBuilder("abc"); StringBuilder s2 = new StringBuilder("abc");
我最终会在堆内存中有两个独立的对象,它们都包含值“abc”?
字符串的不变性与存在常量字符串池几乎没有关系 . 或者更确切地说,它们必须是不可变的,因为字符串池才有用,但它们不一定是字符串池,因为它们是不可变的 .
请注意,通常只有编译时常量会在字符串池中结束 - 除非您调用 intern() . 例如,如果你有:
intern()
char[] x = { 'a', 'b', 'c' }; String s1 = new String(x); String s2 = new String(x);
然后 s1 和 s2 引用相等的字符串,但不同的对象 .
s1
s2
创建两个 StringBuilder 对象只会创建两个对象 . StringBuilder 内部的确切实现细节可以在版本之间轻松更改,而且我不知道详细信息,但它可以很容易地从传递给构造函数的字符串创建 char[] . (无论如何,我相信JDK 1.6就属于这种情况 . )
StringBuilder
char[]
String str1 = "Java" String str2 = "Java"
因此,str1和str2指向文字池中的相同“Java” .
String str3 = new String("Java"); String str4 = new String("Java");
str3和str4没有指向相同的位置,但分配了单独的内存 .
s1和s2不指向相同的内存位置 .
因此,无论何时说“ new ”,它都会为该变量创建一个单独的内存 .
您可以通过在控制台上显示其地址来测试它 .
常量池存储在源代码中定义为文字(用双引号括起来)的字符串 . 非文字字符串不存储在CP中 . 他们只使用底层的 char 数组,并确保它永远不会被写入 .
char
StringBuilder分配这样的数组,然后将其交给新创建的String对象 .
3 回答
字符串的不变性与存在常量字符串池几乎没有关系 . 或者更确切地说,它们必须是不可变的,因为字符串池才有用,但它们不一定是字符串池,因为它们是不可变的 .
请注意,通常只有编译时常量会在字符串池中结束 - 除非您调用
intern()
. 例如,如果你有:然后
s1
和s2
引用相等的字符串,但不同的对象 .创建两个
StringBuilder
对象只会创建两个对象 .StringBuilder
内部的确切实现细节可以在版本之间轻松更改,而且我不知道详细信息,但它可以很容易地从传递给构造函数的字符串创建char[]
. (无论如何,我相信JDK 1.6就属于这种情况 . )因此,str1和str2指向文字池中的相同“Java” .
str3和str4没有指向相同的位置,但分配了单独的内存 .
s1和s2不指向相同的内存位置 .
因此,无论何时说“ new ”,它都会为该变量创建一个单独的内存 .
您可以通过在控制台上显示其地址来测试它 .
常量池存储在源代码中定义为文字(用双引号括起来)的字符串 . 非文字字符串不存储在CP中 . 他们只使用底层的
char
数组,并确保它永远不会被写入 .StringBuilder分配这样的数组,然后将其交给新创建的String对象 .