亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java字符串常量池和字面量賦值的簡單介紹

發布時間:2021-09-14 09:06:39 來源:億速云 閱讀:256 作者:chen 欄目:編程語言

這篇文章主要介紹“Java字符串常量池和字面量賦值的簡單介紹”,在日常操作中,相信很多人在Java字符串常量池和字面量賦值的簡單介紹問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java字符串常量池和字面量賦值的簡單介紹”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

字符串常量池

之所以存在字符串常量池,主要是考慮到String字符串類型比八大基本類型更加復雜,并且使用的頻率也更加頻繁,經常創建字符串對象會造成性能瓶頸,所以采用相似度機制,將字符串進行復用(享元模式)。

在JDK 1.7 之后(包括1.7),字符串常量池已經從方法區移到了堆中。

字面量賦值

String s1 = "古時的風箏";

上面是字符串變量的最常用的方式,這種方式叫做字面量聲明,也就用把字符串用雙引號引起來,然后賦值給一個變量。這種情況下會直接將字符串放到字符串常量池中,然后返回給變量。

Java字符串常量池和字面量賦值的簡單介紹

那這是我再聲明一個內容相同的字符串,會發現字符串常量池中已經存在了,那直接指向常量池中的地址即可。

Java字符串常量池和字面量賦值的簡單介紹

例如上圖所示,聲明了 s1 和 s2,到最后都是指向同一個常量池的地址,所以 s1== s2 的結果是 true。

new String()方式

用 new String() 的方式,但是基本上不建議這么用,除非有特殊的邏輯需要。

String a = "古時的";
String s2 = new String(a + "風箏");

使用這種方式聲明字符串變量的時候,會有兩種情況發生,

字符串常量池之前已經存在相同字符串。

比如在使用 new 之前,已經用字面量聲明的方式聲明了一個變量,此時字符串常量池中已經存在了相同內容的字符串常量。

  • 首先會在堆中創建一個 s2 變量的對象引用;

  • 然后將這個對象引用指向字符串常量池中的已經存在的常量

Java字符串常量池和字面量賦值的簡單介紹

字符串常量池中不存在相同內容的常量

之前沒有任何地方用到了這個字符串,第一次聲明這個字符串就用的是 new String() 的方式,這種情況下會直接在堆中創建一個字符串對象然后返回給變量。

Java字符串常量池和字面量賦值的簡單介紹

我看到好多地方說,如果字符串常量池中不存在的話,就先把字符串先放進去,然后再引用字符串常量池的這個常量對象,這種說法是有問題的,只是 new String() 的話,如果池中沒有也不會放一份進去

基于 new String() 的這種特性,我們可以得出一個結論:

String s1 = "古時的風箏";
String a = "古時的";
String s2 = new String(a + "風箏");
String s3 = new String(a + "風箏");
System.out.println(s1==s2); // false
System.out.println(s2==s3);  // false

以上代碼,肯定輸出的都是 false,因為 new String() 不管你常量池中有沒有,我都會在堆中新建一個對象,新建出來的對象,當然不會和其他對象相等。

intern() 池化

那什么時候會放到字符串常量池呢,就是在使用 intern() 方法之后。 intern() 的定義:

  • 如果當前字符串內容存在于字符串常量池,存在的條件是使用 equas() 方法為true,也就是內容是一樣的,那直接返回此字符串在常量池的引用;

  • 如果之前不在字符串常量池中,那么在常量池創建一個引用并且指向堆中已存在的字符串,然后返回常量池中的地址

第一種情況,準備池化的字符串與字符串常量池中的字符串有相同(equas()判斷)

String s1 = "古時的風箏";
String a = "古時的";
String s2 = new String(a + "風箏");
s2 = s2.intern();

這個字符串常量已經在常量池存在了,這時,再 new 了一個新的對象 s2,并在堆中創建了一個相同字符串內容的對象。

Java字符串常量池和字面量賦值的簡單介紹

這時,s1 == s2 會返回 fasle。然后我們調用 s2 = s2.intern(),將池化操作返回的結果賦值給 s2,就會發生如下的變化。

Java字符串常量池和字面量賦值的簡單介紹

此時,再次判斷 s1 == s2 ,就會返回 true,因為它們都指向了字符串常量池的同一個字符串。

第二種情況,字符串常量池中不存在相同內容的字符串

使用 new String() 在堆中創建了一個字符串對象

Java字符串常量池和字面量賦值的簡單介紹

使用了intern()之后發生了什么呢,在常量池新增了一個對象,但是并沒有將字符串復制一份到常量池,而是直接指向了之前已經存在于堆中的字符串對象。

因為在 JDK 1.7 之后,字符串常量池不一定就是存字符串對象的,還有可能存儲的是一個指向堆中地址的引用,現在說的就是這種情況,注意了,下圖是只調用了 s2.intern(),并沒有返回給一個變量。其中字符串常量池(0x88)指向堆中字符串對象(0x99)就是intern() 的過程。

Java字符串常量池和字面量賦值的簡單介紹

只有當我們把 s2.intern() 的結果返回給 s2 時,s2 才真正的指向字符串常量池。

   public static void main(String[] args) {
 		String s1 = "古時的風箏";
		String s2 = "古時的風箏";
		String a = "古時的";
		String s3 = new String(a + "風箏");
		String s4 = new String(a + "風箏");
	    System.out.println(s1 == s2); // 【1】 true
	    System.out.println(s2 == s3); // 【2】 false
	    System.out.println(s3 == s4); // 【3】 false
	    s3.intern();
	    System.out.println(s2 == s3); // 【4】 false
	    s3 = s3.intern();
	    System.out.println(s2 == s3); // 【5】 true
	    s4 = s4.intern();
	    System.out.println(s3 == s4); // 【6】 true
  }

  • ① 使用字符串直接量時會在常量池創建對象,當然必須是常量折疊之后的。

  • ② 使用new String()時,new產生的字符串對象是位于堆中,而不是常量池中。

  • ③ JDK7之后intern()發生過變化,現在如果常量池中不存在這個對像,不會復制到常量池中,而是簡單的使用堆中已有字符串對象。

  • ④ JDK7以前的intern()不是這樣子的,以前會在常量池中創建一個新的對象,你可以將你的代碼,在JDK6中測試一下,結果應該會不同。所以,你的問題不在new String()上,而是在intern()上,前者與常量池從來就沒有關系。

到此,關于“Java字符串常量池和字面量賦值的簡單介紹”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

呼玛县| 江都市| 顺义区| 郧西县| 安多县| 中西区| 乌恰县| 青龙| 澄迈县| 台东市| 泾川县| 潍坊市| 民县| 寻甸| 新郑市| 巧家县| 昆山市| 铜川市| 九江市| 宜黄县| 华池县| 长阳| 大余县| 晋江市| 辉县市| 武鸣县| 水城县| 云浮市| 济宁市| 河源市| 宁陵县| 东乌珠穆沁旗| 常山县| 黑龙江省| 玉龙| 甘谷县| 石河子市| 高雄县| 安宁市| 庆安县| 正宁县|