經過六個題目完全掌握String筆試面試題

 Java中String類因爲其特殊性(不變類),幾乎是筆試面試中的必考題,固然有些題目其實沒啥意思,不過關鍵是要經過題目掌握原理性的東西。下面六道題目,若是您所有作對了,且明白其因此然,那麼Java中的關於String的筆試面試題應該難不到你了。也許您以爲polaris說的有點過了,然而完全明白這些題目,對理解String類仍是頗有好處的。java

寫出下面各題的打印輸出的結果:面試

1 設計模式

  1. public static void main(String[] args) {  
  2.         String a = "a1";  
  3.         String b = "a" + 1;  
  4.         System.out.println(a == b);  
  5.     }  

 

2數組

  1. public static void main(String[] args) {  
  2.         String a = "ab";  
  3.         String bb = "b";  
  4.         String b = "a" + bb;  
  5.         System.out.println(a == b);  
  6.     }  

 

3函數

  1. public static void main(String[] args) {  
  2.         String a = "ab";  
  3.         final String bb = "b";  
  4.         String b = "a" + bb;  
  5.         System.out.println(a == b);  
  6.     }  

 

4源碼分析

  1. public static void main(String[] args) {  
  2.         String a = "ab";  
  3.         final String bb = getBB();  
  4.         String b = "a" + bb;  
  5.         System.out.println(a == b);  
  6.     }  
  7.   
  8.     private static String getBB() {  
  9.         return "b";  
  10.     }  

 

5設計

  1. private static String a = "ab";  
  2.   
  3. public static void main(String[] args) {  
  4.     String s1 = "a";  
  5.     String s2 = "b";  
  6.     String s = s1 + s2;  
  7.     System.out.println(s == a);  
  8.     System.out.println(s.intern() == a);  
  9. }  

 

6對象

  1. private static String a = new String("ab");  
  2.   
  3.     public static void main(String[] args) {  
  4.         String s1 = "a";  
  5.         String s2 = "b";  
  6.         String s = s1 + s2;  
  7.         System.out.println(s == a);  
  8.         System.out.println(s.intern() == a);  
  9.         System.out.println(s.intern() == a.intern());  
  10.     }  

 

 

(1)經過java源碼分析String繼承

    咱們都知道String是不可變的(immutable),不變性的體現是:String類內部經過char數組來保存字符串,而這個char數組被聲明爲:final。那麼爲何要將String類聲明爲不可變呢?瞭解設計模式的你應該知道有一種模式叫作「不變模式」(immutable pattern),String類的設計就是使用了不變模式,有興趣的朋友能夠看看「不變模式」講的具體是啥東東。索引

    說完String的不可變性,須要說說String的「final性」(其實也仍是不可變性決定的)。這也是有些面試官會問到的問題:我能不能寫一個類繼承自String?爲何?咱們來看看String類的聲明:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence

 

 

    對於final關鍵字的做用不用多解釋了。其實這也是「強不變模式」的一種要求(類自己聲明爲final或全部方法聲明爲final)。

(2)理解String對象的存儲機制

    要深刻理解String必須先了解Java內存機制——運行時數據區(Runtime Data Area)。《The JavaTM Virtual Machine Specification》中將運行時數據區分爲六部分(參看第三章): 1)The pc Register;2)Java Virtual Machine Stacks;3)Heap;4)Method Area;5)Runtime Constant Pool;6)Native Method Stacks;     以上數據區的具體描述可參考規範。須要注意的是,以上只是一個規範說明,並無規定虛擬機如何實現這些數據區。

在說明String對象存儲機制以前,咱們須要先了解數據區的三個部分:Java 虛擬機棧(能夠簡稱爲Java棧)、堆和運行時常量池(簡稱常量池)。對於Java棧和堆你們應該比較熟悉,這裏有一個關鍵點是常量池,下面就重點介紹一下與String相關的常量池。

    首先大概描述一下什麼是常量池:

 

虛擬機必須爲每一個被裝載的類型維護一個常量池。常量池就是該類型所用常量的一個有序集合,包括直接常量(string,integer和floating point常量)和對其餘類型、字段和方法的符號引用。池中的數據項就像數組同樣是經過索引訪問的。由於常量池存儲了相應類型所用到的全部類型、字段和方法的符號引用,因此它在Java程序的動態連接中起着核心的做用。

 

<1> String相關常量池

    在《The JavaTM Virtual Machine Specification》第四章有一節是專門講解各類常量池的,其中有兩個常量池是關於String的。

    1)The CONSTANT_String_info Structure

    對於常量池的細節此文不作過多介紹,polaris之後可能會寫一序列關於Java虛擬機的文章。如今您能夠查閱規範或在網上收集相關資料閱讀。規範上對該常量池結構的介紹是: The CONSTANT_String_info structure is used to represent constant objects of the type String. 在該常量池結構中引用了另外一個常量池結構,如2)

    2)The CONSTANT_Utf8_info Structure

    規範上的描述是:The CONSTANT_Utf8_info structure is used to represent constant string values.

根據上面的介紹能夠看出,字符串字面值會存儲在常量池中。下面來分析String對象的存儲機制。

<2> String對象的存儲

    請看這樣兩個語句:

String x = "abc"; String y = new String("abcd");

 

 如今來分析一下內存的分配狀況。如圖:

    能夠看出,x與y存在棧中,它們保存了相應對象的引用。第一條語句沒有在堆中分配內存,而是將「abc」保存在常量池中。對於第二條語句,一樣會在常量池中有一個「abcd」的字符串,當new時,會拷貝一份該字符串存放到堆中,因而y指向了堆中的那個「abcd」字符串。不知道polaris有沒有講明白。若是您明白了,那麼作前面那六道題就沒什麼問題了。

 

三、六道題答案詳解

1)true

    要說明一點:當兩個字符串字面值鏈接時(相加),獲得的新字符串依然是字符串字面值,保存在常量池中。

2)false

    當字符串字面值與String類型變量鏈接時,獲得的新字符串再也不保存在常量池中,而是在堆中新建一個String對象來存放。很明顯常量池中要求的存放的是常量,有String類型變量固然不能存在常量池中了。

 3)true

    注意此題與上一題的區別,此處是字符串字面值與String類型常量鏈接,獲得的新字符串依然保存在常量池中。

4)false

    此題中第條語句:final String bb = getBB();其實與final String bb = new String(「b」);是同樣的。也就是說return 「b」會在堆中建立一個String對象保存」b」,雖然bb被定義成了final。可見並不是定義爲final的就保存在常量池中,很明顯此處bb常量引用的String對象保存在堆中,由於getBB()獲得的String已經保存在堆中了,final的String引用並不會改變String已經保存在堆中這個事實。

5)false,true

    可能不少人對intern()這個函數不瞭解。JDK API文檔中對intern()方法的描述是:

    返回字符串對象的規範化表示形式。
    一個初始爲空的字符串池,它由類 String 私有地維護。

    當調用 intern 方法時,若是池已經包含一個等於此 String 對象的字符串(用 equals(Object) 方法肯定),則返回池中的字符串。不然,將此 String 對象添加到池中,並返回此 String 對象的引用。

    它遵循如下規則:對於任意兩個字符串 s 和 t,當且僅當 s.equals(t) 爲 true 時,s.intern() == t.intern() 才爲 true。

    全部字面值字符串和字符串賦值常量表達式都使用 intern 方法進行操做。

上面字符串池即爲字符串常量池。明白該題結果的緣由了吧。

6)false,false,true

相關文章
相關標籤/搜索