1. 程式人生 > >搞定java String校招面試題

搞定java String校招面試題

今天大致的閱讀了String類的原始碼,並刷了常見的面試題,在此做個筆記。

面試題一:判斷下列程式執行結果

package String_test;

public class test_1 {
    public static void main(String[] args) {
        String str1 = "HelloWorld";
        String str2 = "HelloWorld";
        String str3 = new String("HelloWorld");
        String str4 = "Hello";
        String str5 = "World";
        String str6 = "Hello" + "World";
        String str7 = str4 + str5;

        System.out.println("str1 == str2 result: " + (str1 == str2));    //1. true

        System.out.println("str1 == str3 result: " + (str1 == str3));    //2. false

        System.out.println("str1 == str6 result: " + (str1 == str6));    //3. true

        System.out.println("str1 == str7 result: " + (str1 == str7));    //4. false

        System.out.println("str1 == str7.intern() result: " + (str1 == str7.intern()));        //5. true

        System.out.println("str3 == str3.intern() result: " + (str3 == str3.intern()));        //6.false
    }
}

畫記憶體圖逐個的分析每種情況:第一個:str1與str2指向同一個地址,故相等。

第二個:new代表建立了一個物件,str3指向堆記憶體中的引用,故str1與str3指向的地址不同。需要注意的是:字串常量池中不可能存在兩個一樣的字串值,向這裡堆記憶體指向的實際還是執行時常量池中的HelloWorld值

 

第三個:由於“Hello”與“World”都是常量,用+號在編譯時會被自動編譯成String str6 = "HelloWorld",所以兩個引用都是指向常量池中的地址

 

第四個:關鍵點在於理解String str7 = str4+str5。在jdk文件中有這麼一段話

java語言提供了字串串聯運算子特殊支援( + ),和其他物件轉換為字串。字串連線是通過StringBuilder實施(或StringBuffer)類及其append方法。字串的轉換是通過方法toString實施,由Object和繼承的所有類的java。

可見jvm會在堆中建立一個以str4為基礎的StringBuilder物件,在通過append方法新增,最後通過toSting()返回一個String物件。故str7指向的還是堆記憶體的物件而str1指向的是常量池中的地址,兩者指向地址不相同。

 

第五個:intern方法使用:一個初始為空的字串池,它由類String獨自維護。當呼叫 intern方法時,如果池已經包含一個等於此String物件的字串(用equals(oject)方法確定),則返回池中的字串。否則,將此String物件新增到池中,並返回此String物件的引用。這裡str1指向常量池中的“HelloWorld”物件,str7.intern():此時常量池中已經有"HelloWorld"字串值,所以地址指向相同

 

第六個:str3指向的是堆記憶體,而str3.intern()返回的是常量池中已有字串“HelloWorld”的引用,故兩者指向地址不同。

 

面試題二:java中的String為什麼設計為final類?

1. 允許String物件快取hashCode值:在java中String型別是非常常用的,涉及到大量的增刪改查。字串不變性保證了hashCode的唯一性,這是一種優化手段意味著不必每次都去計算hash值,這也是為什麼HashMap建議用String,Integer這種不可變物件當作Key值
2. 字串常量池需要:java中將字串值存放在字串常量池中,如果String物件是可變的,會產生很多邏輯錯誤,比如改變一個物件會影響到另一個獨立物件。
3. 安全性:網路地址的url,檔案路徑path通常情況啊下都是用String型別來儲存,如果不是固定不變的可能產生很多安全隱患。

 

面視題三:有什麼辦法可以改變String?

如果問了這個就很尷尬,sun公司特意設計的不可變,要強行改變只能通過反射這種騷操作

package String_test;

import java.lang.reflect.Field;

public class test_2 {
    public static void main(String[] args) throws Exception {
        String str = "王老吉真解渴";
        System.out.println("str=:  "+str);
        
        //通過反射改變獲取內部的value字元陣列
        Field field = String.class.getDeclaredField("value");
        field.setAccessible(true);
        field.set(str, new char[]{'加','多','寶','也','解','渴'});
        
        System.out.println("str=:  "+str);
    }
}

 

面試題四:下列程式碼建立了幾個物件?

String st1 = new String(“abc”);

常量池一個“abc”物件,堆中一個"abc"物件,總共兩個。

String st1 = new String(“abc”);
String st2 = new String(“abc”);

3個物件。 字串在常量池中是唯一的,堆記憶體中有兩個,常量池中一個。

 

面試題五:談一下String,StringBuilder,StringBuffer的區別?

1.String類是字串常量,而StringBuilder與StringBuffer是字串變數。前者不可變後者可變

2.StringBuilder是非同步的,StringBuffer類的API都套上了一層synchronized同步修飾,所以StringBuffer適合在多執行緒場景使用(實際基本不用),StringBuilder類適合單執行緒使用,它兩用的多的就是append和insert方法

它三的適用場景可以看下知乎:https://www.zhihu.com/question/20101840

小結:

關於String類和它的成員方法,都是被final修飾的,意味著Strin類不可被繼承。String底層是採用字元陣列對資料進行操作的,關於String的一切操作jdk底層都是會new一個新的String物件,在它的基礎上進行操作。所以String是不可變的。

關於String,基礎性的理論大致就這些,更多的還會考察字串的一些演算法,這部分也是需要攻克的一個難點!!

參考連結:https://www.cnblogs.com/xiaoxi/p/6036701.html

參考連結:https://blog.csdn.net/yissan/article/details/7874