string str="i"與 String str=new String("i")和String s = new String("abc")的解釋!!!

string str="i"與 String str=new String(“i”)

String x = "張三";
String y = "張三";
String z = new String("張三");
System.out.println(x == y); // true
System.out.println(x == z); // false

爲什麼會輸出上邊的結果呢,String x = “張三” 的方式,Java 虛擬機會將其分配到常量池中,而常量池中沒有重複的元素,比如當執行“張三”時,java虛擬機會先在常量池中檢索是否已經有“張三”,如果有那麼就將“張三”的地址賦給變量,如果沒有就創建一個,然後在賦給變量;而 String z = new String(“張三”) 則會被分到堆內存中,即使內容一樣還是會創建新的對象。

如果還有疑惑,可參考String s = new String(“abc”);產生了幾個對象?

String s = new String(“abc”)

對於這個問題,老套路先上代碼:

public class StringTest {
	public static void main(String[] args){
		String s1="Hello";
		String s2="Hello";
		String s3=new String("Hello");
		System.out.println("s1和s2 引用地址是否相同:"+(s1 == s2));
		System.out.println("s1和s2 值是否相同:"+s1.equals(s2));
		System.out.println("s1和s3 引用地址是否相同:"+(s1 == s3));
		System.out.println("s1和s3 值是否相同:"+s1.equals(s3));
	}
}

執行結果:

在這裏插入代碼片s1和s2 引用地址是否相同:true
s1和s2 值是否相同:true
s1和s3 引用地址是否相同:false
s1和s3 值是否相同:true

上面程序中的"==“是判斷兩個對象引用的地址是否相同,也就是判斷是否爲同一個對象,s1與s2 返回爲true,s1與s3返回則是false。說明s1與s2 引用的同一個對象的地址,s3則與其它兩個引用不是同一個對象地址。
Java爲了避免產生大量的String對象,設計了一個字符串常量池。工作原理是這樣的,創建一個字符串時,JVM首先爲檢查字符串常量池中是否有值相等的字符串,如果有,則不再創建,直接返回該字符串的引用地址,若沒有,則創建,然後放到字符串常量池中,並返回新創建的字符串的引用地址。所以上面s1與s2引用地址相同。
那爲什麼s3與s1、s2引用的不是同一個字符串地址呢? String s3=new String(“Hello”); JVM首先是在字符串常量池中找"Hello” 字符串,如果沒有創建字符串常量,然後放到常量池中,若已存在,則不需要創建;當遇到 new 時,還會在內存(不是字符串常量池中,而是在堆裏面)上創建一個新的String對象,存儲"Hello",並將內存上的String對象引用地址返回,所以s3與s1、s2引用的不是同一個字符串地址。內存結構圖如下:
在這裏插入圖片描述

從內存圖可見,s1與s2指向的都是常量池中的字符串常量,所以它們比較的是同一塊內存地址,而s3指向的是堆裏面的一塊地址,說的具體點應該是堆裏面的Eden區域,s1跟s3,s2跟s3比較都是不相等的,都不是同一塊地址。

瞭解了String類的工作原理,迴歸問題本身:
在String的工作原理中,已經提到了,new一個String對象,是需要先在字符串常量中查找相同值或創建一個字符串常量(有則用沒有則創建),然後再在內存中創建一個String對象,所以String str = new String(“xyz”); 會創建一個或兩個對象。

——————————————
版權聲明:本文爲CSDN博主「-小酒窩-」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zx1293406/article/details/103548506

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章