我最近了解到在Java中:==比较对象引用,而不是内容,这就是为什么:
String str1 = "hell";
String str2 = "o";
String str3 = str1 + str2;
String str4 = "hello";
str3 == str4; // False
到目前为止一切顺利。但是,当我执行以下操作时:
String str5 = "hello";
str5 == str4; // True
这是否意味着str5和str4引用相同的内存对象?这是如何工作的呢?
String str5 = "hello";
创建了一个池字符串值hello
,这就是为什么str5 == str4
返回true
。
另一方面,str1 + str2
是这样工作的:
- 创建StringBuilder类的一个实例(在幕后)
-
+
操作符实际上调用StringBuilder#append(String s)方法 当追加操作完成后,调用StringBuilder.toString()方法,返回一个全新的String对象。这就是为什么
str3 == str4
实际上是false
。更多信息:
- 如何比较Java中的字符串?
- Java如何使用"+"进行字符串连接?
是。str5
和str4
引用同一个内存对象。因为字符串是不可变的,当你改变一些字符串的值时,它会产生一个不同的对象。如果两个String
对象具有相同的值,则不会创建第二个对象,JVM只给出第一个对象的引用。
当字符串的值发生变化时,为了一些安全和其他有用的目的而创建了不同的对象,请读取这些链接:
字符串的不变性
wiki不可变对象
当创建一些字符串时,例如
String str1="hello";
当您再次尝试创建具有相同值的字符串时,JVM将创建一个不可变对象
String str2="hello"
JVM使用相同的过程来创建一个对象,如果这个对象已经创建,那么它返回str1
的对象,以减少重复的对象创建。这将是jvm中有用的字符串池
是的,当您创建并分配字符串值例如String s1="hello";
时,它会被添加到字符串池中。现在,如果您将相同的String值分配给另一个引用,像这样:-
String s2="hello";
变量s2将指向字符串池中存在的同一个String对象hello
。
但是你可以为相同的值强制创建一个新的String对象,像这样:-
String s3= new String("hello");
这将为hello
添加和创建新对象,即使它已经存在于字符串池中。
因此可以总结为:-
s1==s2; //return true
s1==s3; //return false
s2==s3; //returns false
字符串在创建后由JVM池化,这就是为什么这些变量在字符串池中引用相同的实例。
使用String池是为了避免不必要的对象创建
字符串是不可变的对象。这就是为什么str1
和str2
加起来不等于str3
的原因。
是的,它为str5 ==str4提供true,因为它使用"字符串池区域"来存储。这一次也是它比较对象引用",但是这些字符串有相同的对象引用,因为字符串池区域有一个对象id。在第一种情况下,字符串不是在字符串池区域创建的,这就是为什么它给出false。
字符串字量的私有池由string类维护。所有字面值字符串和字符串值常量表达式在程序启动时被添加到这个池中。所以所有具有相同值的字符串字面值将指向相同的对象。
当一个新的字符串对象被创建时(例如:通过连接两个字符串对象),它不属于string池,因此将它与另一个字符串文字进行比较将返回false。任何字符串对象都可以通过调用intern()方法添加到字符串池中,现在该对象将指向池中与该对象具有相同值的字符串字面值。现在这个对象与相同字符串字面值的任何字符串比较都将产生true