【005期】JavaSE面試題(五):String類

開篇介紹

你們好,我是Java最全面試題庫的提褲姐,本篇文章是面試系列文章的第五篇,主要介紹了JavaSE中String相關的面試題,在以後會順着開篇的思惟導圖一直總結下去,作到日更!若是我能作到百日百更,但願你也能夠跟着百日百刷,一百天養成一個好習慣。java

1、String、StringBuffer、StringBuilder 的區別?

  • 都是final類,都不容許被繼承
  • String長度是不可變的,StringBuffer和StringBuilder長度是可變的。
  • StringBuffer是線程安全的,StringBuilder是線程不安全的,但他們兩個中的全部方法都是相同的,StringBuffer在StringBuilder的方法之上加了synchronized修飾,保證線程安全。
  • StringBuilder比StringBuffer擁有更好的性能。
  • 若是一個String類型的字符串,在編譯時就能夠肯定是一個字符串常量,則編譯完成以後,字符串會自動拼接成一個常量。此時String的速度比StringBuilder和StringBuffer的性能更好。

2、String str="aaa" 與 String str=new String("aaa")同樣嗎?

不一樣,內存分配的方式不一樣。
String str="aaa",建立了1個對象,建立的"aaa"是常量,jvm將其分配在常量池中;
String str=new String("aaa"),建立了2個對象,一個是在常量池中,一個在堆內存中。面試

3、String str="aa" ,String s="bb" ,String aa=aa+s;一共建立了幾個對象?

一共有2個引用,3個對象;
"aa"與"bb"都是常量,常量的值不能改變,當執行字符串拼接的時候,會建立一個新的常量"aabb",將其存到常量池中。安全

4、String s = "Hello";s = s + " world!";這兩行代碼執行後,原始的 String 對象中的內容到底變了沒有?

沒有。
由於 String 被設計成不可變(immutable)類,因此它的全部對象都是不可變對象。在這段代碼中,s 原先指
向一個 String 對象,內容是 "Hello",而後咱們對 s 進行了「+」操做,那麼 s 所指向的那個對象是沒有發生變化的。這時,s 不指向原來那個對象了,而指向了另外一個 String 對象,內容爲"Hello world!",原來那個對象還存在於內存之中,只是 s 這個引用變量再也不指向它了。
結論,若是常常對字符串進行各類各樣的修改,或者說,不可預見的修改,那麼使用 String 來表明字符串的話會引發很大的內存開銷。由於 String 對象創建以後不能再改變,因此對於每個不一樣的字符串,都須要一個 String 對象來表示。這時,應該考慮使用 StringBuffer 類,它容許修改,而不是每一個不一樣的字符串都要生成一個新的對象。而且,這兩種類的對象轉換十分容易。同時,若是要使用內容相同的字符串,沒必要每次都 new 一個 String。例如要在構造器中對一個名叫 s 的 String 引用變量進行初始化,把它設置爲初始值,應當這樣作:多線程

public class Demo {
  private String s;
  ...
  s = "Initial Value";
  ...
}

而非s = new String("Initial Value");
後者每次都會調用構造器,生成新對象,性能低下且內存開銷大,而且沒有意義,由於 String 對象不可改變,因此對於內容相同的字符串,只要一個 String 對象來表示就能夠了。也就說,屢次調用上面的構造器建立多個對象,他們的 String 類型屬性 s 都指向同一個對象。
上面的結論還基於這樣一個事實:
對於字符串常量,若是內容相同,Java 認爲它們表明同一個 String 對象。
而用關鍵字 new 調用構造器,老是會建立一個新的對象,不管內容是否相同。
至於爲何要把 String 類設計成不可變類,是它的用途決定的。其實不僅 String,不少 Java 標準類庫中的類都是不可變的。在開發一個系統的時候,咱們有時候也須要設計不可變類,來傳遞一組相關的值,這也是面向對象思想的體現。
不可變類有一些優勢,好比由於它的對象是隻讀的,因此多線程併發訪問也不會有任何問題。
固然也有一些缺點,好比每一個不一樣的狀態都要一個對象來表明,可能會形成性能上的問題。因此 Java 標準類庫還提供了一個可變版本,即 StringBuffer。併發

5、判斷下面代碼的執行結果

String s1 = new String("abc");    
String s2 = "abc";
System.out.println(s1 == s2);   //false
System.out.println(s1.equals(s2));   //true

緣由:s1記錄的是堆內存中對象的地址,s2記錄的是常量池中的地址jvm

String s1 = "a" + "b" + "c";
String s2 = "abc";
System.out.println(s1 == s2);        //true    
System.out.println(s1.equals(s2));   //true

緣由:java中有常量優化機制,編譯時就把 "a" + "b" + "c"變成「abc」賦值給s1性能

String s1 = "ab";
String s2 = "abc";
String s3 = s1 + "c";
System.out.println(s3 == s2);            //false
System.out.println(s3.equals(s2));       //true

緣由:由於s1是一個變量,jvm運行的時候不認爲s3="abc",也就是沒法使用常量池。所以s3會從新建立一個對象。優化

相關文章
相關標籤/搜索