我的问题是什么是在字符串池中创建字符串对象以及在声明字符串时在Heap上创建字符串对象的用途是什么String a = new String("abc");?
为什么我们在创建字符串时在堆中创建字符串String a = "abc".
如果我跑,我会得到什么is,==做什么以及为什么
a = "ab"
b = "ab"
a == b
Run Code Online (Sandbox Code Playgroud)
我得到True.这里的问题是为什么会发生这种情况:
a = "ab"
b = "ab"
a is b # Returns True
Run Code Online (Sandbox Code Playgroud)
所以我做了我的研究,我找到了这个.答案说Python解释器使用字符串池.因此,如果它看到两个字符串相同,则将它们分配id给新字符串以进行优化.
直到这里一切都好,并回答.我真正的问题是为什么这个池只发生在一些字符串上.这是一个例子:
a = "ab"
b = "ab"
a is b # Returns True, as expected knowing Interpreter uses string pooling
a = "a_b"
b = "a_b"
a is b # Returns True, again, as expected knowing Interpreter uses string …Run Code Online (Sandbox Code Playgroud) 如果字符串池上有许多字符串文字并且内存不足,会发生什么.是否会增加它的大小,如果是的话怎么样?如果没有,如果我尝试创建更多的字符串文字会发生什么?
下面是String.intern()方法的Javadoc注释:
*返回字符串对象的规范表示.
最初为空的字符串池由String类私有维护.
调用实习方法时,如果池已经包含等于此字符串对象的字符串(由equals(Object)方法确定),则返回池中的字符串.否则,将此String对象添加到池中,并返回对此String对象的引用.
因此,对于任何两个字符串s和t,当且仅当s.equals(t)为真时,s.intern()== t.intern()才为真.
所有文字字符串和字符串值常量表达式都是实体.字符串文字在The Java™Language Specification的3.10.5节中定义."
但我觉得有些事情从jdk-8u102开始改变了.
检查以下示例:
public class Test1 {
public static void main(String[] args) {
String s1 = new String(new char[]{'J', 'a', 'v', 'a'});
String s2 = s1.intern();
System.out.println(s1 == s2);
}
}
Run Code Online (Sandbox Code Playgroud)
如果在JDK 7u80(JDK 7的最后稳定版本)和JDK 8到8u101上运行以上程序,则输出为:
true
但是如果你在JDK 8u102以及JDK 9和JDK 10中运行以上程序,则输出为:
false
为什么intern()方法开始表现不同JDK 8u102以后?
我检查了发行说明和Javadoc注释,但在JDK 8u102中找不到与intern()方法相关的更改.
我查了博客和其他网站,但没有运气.
但是当我尝试使用其他字符串时,输出没有变化:
public class Test2 {
public static void main(String[] args) {
String s3 = new String(new char[]{'U', 'd', 'a', 'y', 'a', 'n'});
String s4 = …Run Code Online (Sandbox Code Playgroud) 在浏览有关字符串池及其多年来的变化的这篇文章时,我遇到了以下声明:
在Java 7u40之前,默认池大小为1009个存储桶,但此值在较新的Java版本中受到一些更改。确切地说,从Java 7u40到Java 11的默认池大小为60013,现在增加到65536。
那么,字符串池中的存储桶是什么?这些如何与实习字符串的数量相媲美?这个概念类似于哈希图中的存储桶吗?
String s1 = "Hello".concat("World");
String s3 = new String("HelloWorld"); //Line-2
String s2 = s1.intern();
System.out.println(s1 == s2); //false
System.out.println(s1 == s3); //false
System.out.println(s2 == s3); //false
Run Code Online (Sandbox Code Playgroud)
如果我删除了Line-2并比较了s1 == s2,它将返回true.谁能解释一下Line-2之后字符串池中到底发生了什么?什么在堆中和常量池中的每一行中发生了什么?
根据我的理解,s1将在常量池中创建"HelloWorld".但是仍然s1 == s2是假的?
这可能是重复的,但找不到我需要的解释。有人可以向我解释一下吗?
如果我是对的:
String s1 = "a";
String s2 = "a";
Run Code Online (Sandbox Code Playgroud)
s1和s2都会指向字符串池中的同一个地址,并且只有一个值为“a”的对象。
现在,如果我这样做:
String s1 = "a"; //line A
s1 = s1.concat("b"); //line B; I don't understand what's happening here in terms of references
String s2 = "ab";//line C
System.out.println(s1 == s2); //false
Run Code Online (Sandbox Code Playgroud)
为什么我得到false?
我的看法(可能是错误的)是这样的:
after line Aa->在字符串池中创建对象(值为),由 引用s1;
after line B-> 在字符串池中创建具有值的对象b(没有引用),然后ab在字符串池中创建具有值的新对象(由现有的引用s1)
after line C->(这可能是我错了)由于具有值的现有对象ab(由现有的引用)s1) 使用 (或 +) 创建concat(),JVM 不会重用该引用指向的对象 …
Integer、Character、Double 等——所有这些都是像 String 这样的不可变类。String 有 Stringpool 来节省内存,但为什么这些包装器没有类似的池?
我检查过:Integer 有一个类似的池,最多只有 127 个,但不会更多。
我们所有人都知道String在java中是不可变的 - 一旦创建了字符串,就无法更改内容.
String使用字符数组char[] value来存储字符串内容,这里是java代码 -
/** The value is used for character storage. */
private final char value[];
Run Code Online (Sandbox Code Playgroud)
如果我们可以访问该字段values[]并进行更改,该怎么办?看到这段代码 -
String name = "Harish";
System.out.println(name); // Harish
Field field = name.getClass().getDeclaredField("value");
field.setAccessible(true);
char[] value = (char[]) field.get(name);
value[0] = 'G';
value[1] = 'i';
System.out.println(Arrays.toString(value)); // [G, i, r, i, s, h]
System.out.println(name); // Girish
Run Code Online (Sandbox Code Playgroud)
这样,我认为,我们可以改变字符串的内容,这违反了字符串不变性原则.
我错过了什么吗?
我想了解当我们在 Java 中对字符串使用 + 和 += 时如何分配内存。我知道字符串文字存储在字符串常量池中,在案例#1 中,s1 和 s2 都引用字符串常量池中的相同内存。
在案例#2 中,即使我使用了 + 运算符,它仍然引用字符串常量池中的同一个对象
我觉得有趣的是案例#3。在这种情况下如何以及在哪里分配内存?它与案例#2 有何不同
//Case #1
String s1 = "Hello Java";
String s2 = "Hello Java";
System.out.println(s1 == s2); //true
//Case #2
s1 = "Hello" + " Java";
s2 = "Hello Java";
System.out.println(s1 == s2); //true
s1 = "Hello";
s1 += " Java";
s2 = "Hello Java";
System.out.println(s1 == s2); //false
Run Code Online (Sandbox Code Playgroud) string-pool ×10
java ×9
string ×9
immutability ×2
heap-memory ×1
memory ×1
python ×1
wrapper ×1