是不是定义字符串如果不使用new来初始化的话相同的字符串会被定义成一个引用
闭关修行中......
JVM對於String的存储有一点特殊的地方在于有一块String常量池。 這個常數池裡面存著String物件的引用。
String
String常量池
比如,String s = "abc"会先去String常量池中查找有没有已经存在的引用,如果没有,声明的abc会直接生成一个String对象,并且会在String常量池中存入一個引用指向這個String物件。
String s = "abc"
之後直接宣告的字串同樣也會遵循上面的步驟,所以第二次String s2 = "abc"从String常量池中找到了一個引用指向第一次宣告的字串物件。
String s2 = "abc"
而new String("abc")这样会直接在堆中创建新的对象,不会进入String常量池。要把这样的对象引用放入常量池中就涉及另一个String类的方法intern(),這個方法就是回傳一個String物件的常數池引用。如果這個物件不在常數池中,就會把這個String物件放入常數池中並傳回對應的物件參考。
new String("abc")
intern()
題主第一個截圖的方法str2.intern() == str3.intern()这样使用也会返回true,调用intern()返回的String常量池引用是同一個。
str2.intern() == str3.intern()
true
Java中所有非內建資料型別都是引用。
String s = new String("xx");這種方式會建立一塊記憶體空間,並使引用s指向它。
String s = "xx";這種方式會使引用s指向一塊共享的空間。
使用new的方式建立時str2和str3所指向的不同的記憶體空間,故str2和str3是不相等的。
直接使用字串賦值時str2和str3指向是的相同的記憶體空間,故str2和str3是相等的。
可以使用str2.equals(str3)來比較字串的內容。
一個是在常數池中存儲,一個是在堆中new出新物件
幫助你理解這個過程。 java中有幾個點你可以記住下1.所有的字串都會在常數池生成,對應的是CONSTANT_String_info,不可變。 2.普通的物件幾乎都是在堆中生成(當然也有一些比較特殊的比如Class類的對象可能在方法區生成,這個看不同的虛擬機實現,虛擬機規範並沒有強制)3.= =這個判定的時候,對於引用型,說到底都是比對記憶體位址。
好了,有了上述的觀念。在第一個問題中,String s1 = new String("aaa"); 當你new一個對象,jvm就會在堆上幫你開闢一個對象空間,而s1是存在你的本地變數表的,s1指向這個物件空間(可以暫時理解為s1存著物件空間的位址)。所以你new了兩個,是兩個不同的物件空間。 ==判斷當然不同啦,因為,s1和s2指向不同的空間。
第二個問題,上述第一點,每個字串都只會在常數池中存在一份,所以str2指向這個常數池字串的位址,str3也是指向這個常數池字串的位址。 ==判斷自然是相同的。
JVM對於
String
的存储有一点特殊的地方在于有一块String常量池
。這個常數池裡面存著String物件的引用。
比如,
String s = "abc"
会先去String常量池
中查找有没有已经存在的引用,如果没有,声明的abc会直接生成一个String对象,并且会在String常量池
中存入一個引用指向這個String物件。之後直接宣告的字串同樣也會遵循上面的步驟,所以第二次
String s2 = "abc"
从String常量池
中找到了一個引用指向第一次宣告的字串物件。而
new String("abc")
这样会直接在堆中创建新的对象,不会进入String常量池
。要把这样的对象引用放入常量池中就涉及另一个String类的方法intern()
,這個方法就是回傳一個String物件的常數池引用。如果這個物件不在常數池中,就會把這個String物件放入常數池中並傳回對應的物件參考。題主第一個截圖的方法
str2.intern() == str3.intern()
这样使用也会返回true
,调用intern()
返回的String常量池
引用是同一個。Java中所有非內建資料型別都是引用。
String s = new String("xx");這種方式會建立一塊記憶體空間,並使引用s指向它。
String s = "xx";這種方式會使引用s指向一塊共享的空間。
使用new的方式建立時str2和str3所指向的不同的記憶體空間,故str2和str3是不相等的。
直接使用字串賦值時str2和str3指向是的相同的記憶體空間,故str2和str3是相等的。
可以使用str2.equals(str3)來比較字串的內容。
一個是在常數池中存儲,一個是在堆中new出新物件
幫助你理解這個過程。 java中有幾個點你可以記住下
1.所有的字串都會在常數池生成,對應的是CONSTANT_String_info,不可變。
2.普通的物件幾乎都是在堆中生成(當然也有一些比較特殊的比如Class類的對象可能在方法區生成,這個看不同的虛擬機實現,虛擬機規範並沒有強制)
3.= =這個判定的時候,對於引用型,說到底都是比對記憶體位址。
好了,有了上述的觀念。在第一個問題中,
String s1 = new String("aaa"); 當你new一個對象,jvm就會在堆上幫你開闢一個對象空間,而s1是存在你的本地變數表的,s1指向這個物件空間(可以暫時理解為s1存著物件空間的位址)。所以你new了兩個,是兩個不同的物件空間。 ==判斷當然不同啦,因為,s1和s2指向不同的空間。
第二個問題,上述第一點,每個字串都只會在常數池中存在一份,所以str2指向這個常數池字串的位址,str3也是指向這個常數池字串的位址。 ==判斷自然是相同的。