1. 程式人生 > >面試------String 類和常量池

面試------String 類和常量池

String 類和常量池

1 String 物件的兩種建立方式:

     String str1 = "abcd";
     String str2 = new String("abcd");
     System.out.println(str1==str2);//false

這兩種不同的建立方法是有差別的,第一種方式是在常量池中拿物件,第二種方式是直接在堆記憶體空間建立一個新的物件。  記住:只要使用new方法,便需要建立新的物件。

2 String 型別的常量池比較特殊。它的主要使用方法有兩種:

  • 直接使用雙引號宣告出來的 String 物件會直接儲存在常量池中。
  • 如果不是用雙引號宣告的 String 物件,可以使用 String 提供的 intern 方法。String.intern() 是一個 Native 方法,它的作用是:如果執行時常量池中已經包含一個等於此 String 物件內容的字串,則返回常量池中該字串的引用;如果沒有,則在常量池中建立與此 String 內容相同的字串,並返回常量池中建立的字串的引用。
	      String s1 = new String("計算機");
	      String s2 = s1.intern();
	      String s3 = "計算機";
	      System.out.println(s2);//計算機
	      System.out.println(s1 == s2);//false,因為一個是堆記憶體中的String物件一個是常量池中的String物件,
	      System.out.println(s3 == s2);//true,因為兩個都是常量池中的String物件

3 String 字串拼接

		  String str1 = "str";
		  String str2 = "ing";
		  
		  String str3 = "str" + "ing";//常量池中的物件
		  String str4 = str1 + str2; //在堆上建立的新的物件	  
		  String str5 = "string";//常量池中的物件
		  System.out.println(str3 == str4);//false
		  System.out.println(str3 == str5);//true
		  System.out.println(str4 == str5);//false

儘量避免多個字串拼接,因為這樣會重新建立物件。如果需要改變字串的話,可以使用 StringBuilder 或者 StringBuffer。

String s1 = new String("abc");這句話建立了幾個物件?

建立了兩個物件。

驗證:

		String s1 = new String("abc");// 堆記憶體的地值值
		String s2 = "abc";
		System.out.println(s1 == s2);// 輸出false,因為一個是堆記憶體,一個是常量池的記憶體,故兩者是不同的。
		System.out.println(s1.equals(s2));// 輸出true

結果:

false
true

解釋:

先有字串"abc"放入常量池,然後 new 了一份字串"abc"放入Java堆(字串常量"abc"在編譯期就已經確定放入常量池,而 Java 堆上的"abc"是在執行期初始化階段才確定),然後 Java 棧的 str1 指向Java堆上的"abc"。

8種基本型別的包裝類和常量池

  • Java 基本型別的包裝類的大部分都實現了常量池技術,即Byte,Short,Integer,Long,Character,Boolean;這5種包裝類預設建立了數值[-128,127]的相應型別的快取資料,但是超出此範圍仍然會去建立新的物件。
  • 兩種浮點數型別的包裝類 Float,Double 並沒有實現常量池技術。
		Integer i1 = 33;
		Integer i2 = 33;
		System.out.println(i1 == i2);// 輸出true
		Integer i11 = 333;
		Integer i22 = 333;
		System.out.println(i11 == i22);// 輸出false
		Double i3 = 1.2;
		Double i4 = 1.2;
		System.out.println(i3 == i4);// 輸出false

Integer 快取原始碼:

/**
*此方法將始終快取-128到127(包括端點)範圍內的值,並可以快取此範圍之外的其他值。
*/
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

應用場景:

  1. Integer i1=40;Java 在編譯的時候會直接將程式碼封裝成Integer i1=Integer.valueOf(40);,從而使用常量池中的物件。
  2. Integer i1 = new Integer(40);這種情況下會建立新的物件。
  Integer i1 = 40;
  Integer i2 = new Integer(40);
  System.out.println(i1==i2);//輸出false

Integer比較更豐富的一個例子:

  Integer i1 = 40;
  Integer i2 = 40;
  Integer i3 = 0;
  Integer i4 = new Integer(40);
  Integer i5 = new Integer(40);
  Integer i6 = new Integer(0);
  
  System.out.println("i1=i2   " + (i1 == i2));
  System.out.println("i1=i2+i3   " + (i1 == i2 + i3));
  System.out.println("i1=i4   " + (i1 == i4));
  System.out.println("i4=i5   " + (i4 == i5));
  System.out.println("i4=i5+i6   " + (i4 == i5 + i6));   
  System.out.println("40=i5+i6   " + (40 == i5 + i6));     

結果:

i1=i2   true
i1=i2+i3   true
i1=i4   false
i4=i5   false
i4=i5+i6   true
40=i5+i6   true

解釋:

語句i4 == i5 + i6,因為+這個操作符不適用於Integer物件,首先i5和i6進行自動拆箱操作,進行數值相加,即i4 == 40。然後Integer物件無法與數值進行直接比較,所以i4自動拆箱轉為int值40,最終這條語句轉為40 == 40進行數值比較。