Java面試題之String常見問題

1、創建String的兩種方式
String s1 = "abc";
String s2 = new String("abc");
2、String不能被繼承,因爲String類被final修飾

String的對象一旦被創建,則不能修改,是不可變的,所謂的修改其實是創建了新的對象,所指向的內存空間不變,因爲String是不可變類,所以可以安全的用於多線程中。
在這裏插入圖片描述

3、比較兩個字符串的方法

String內部實現了Comparable接口,有兩個比較方法:compareTo(String anotherString) 和compareToIgnoreCase(String str)
①、compareTo()方法
與傳入的anotherString字符串進行比較,如果小於傳入的字符串返回負數,如果大於則返回正數。當兩個字符串值相等時,返回0,此時eqauls方法會返回true。
②、compareToIgnoreCase()方法
該方法與compareTo方法類似,區別只是內部利用了toUpperCase等方法進行了大小寫轉換後進行比較。

4、String、StringBuilder、StringBuffer的區別

①、String是不可變類,每當我們對String進行操作的時候,總是會創建新的字符串。操作String很耗資源,所以Java提供了兩個工具類來操作String:StringBuffer和StringBuilder。
②、StringBuffer,也被final修飾,不可被繼承,但是它是可變類,絕大多數方法都進行了同步處理。
③、StringBuilder,StringBuilder是JDK1.5發佈的,它和StringBuffer本質上沒什麼區別,就是去掉了保證線程安全的那部分,減少了開銷。

5、字符串常量池

例一:

public static void main(String[] args){
        String s1 = "a";
        String s2 = "a";
        System.out.println(s1 == s2); //true,比較地址值,都在常量池,相等
        System.out.println(s1.equals(s2)); //true,equals中,先判斷兩個對象的地址值,地址值相同,默認就是同一個對象,不會繼續equals中的具體值是否相等的判斷了,直接會返回true。
    }

例二:

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

例三:

String s1 = "a" + "b" + "c";
String s2 = "abc";
System.out.println(s1 == s2);          //true         地址值相同,都是常量,在常量池裏面        
System.out.println(s1.equals(s2));    //true   地址值相同,默認同一個對象,值當然也是相等的。

例四:

String s1 = "ab";
String s2 = "abc";
String s3 = s1 + "c";
System.out.println(s3 == s2);               //false   不相等,s1是變量,編譯的時候確定不了值,在內存中會創建值,s3在堆內存中,。s2在常量池,所以不相等。
System.out.println(s3.equals(s2));      //true   比較兩個對象的值相等。

例五:

String s1 = "a";
String s2 = "a";
String s3 = "a" + s2;
String s4 = "a" + "a";
String s5 = s1 + s2;
//表達式只有常量時,編譯期完成計算
//表達式有變量時,運行期才計算,所以地址不一樣
System.out.println(s3 == s4); //false
System.out.println(s3 == s5); //false
System.out.println(s4 == "aa"); //true

例六:

String s3 = new String("xyz");
String s4 = new String("xyz");
System.out.println(s3==s4);

對例六解釋如下:
結果是 false

採用new關鍵字新建一個字符串對象時,JVM首先在字符串池中查找有沒有"xyz"這個字符串對象,如果有,則不在池中再去創建"xyz"這個對象了,直接在堆中創建一個"xyz"字符串對象,然後將堆中的這個"xyz"對象的地址返回賦給引用s3,這樣,s3就指向了堆中創建的這個"xyz"字符串對象;如果沒有,則首先在字符串池中創建一個"xyz"字符串對象,然後再在堆中創建一個"xyz"字符串對象,然後將堆中這個"xyz"字符串對象的地址返回賦給s3引用,這樣,s3指向了堆中創建的這個"xyz"字符串對象。s4則指向了堆中創建的另一個"xyz"字符串對象。s3 、s4是兩個指向不同對象的引用,結果當然是false。

例七:

String s1 = "abc";
StringBuffer s2 = new StringBuffer(s1);
System.out.println(s1.equals(s2));
//輸入false,因爲s2不是String類型,String的equals方法進行了類型判斷
6、String的intern()方法

當intern()方法被調用,如果字符串池中含有一個字符串和當前調用方法的字符串eqauls相等,那麼就會返回池中的字符串。如果池中沒有的話,則首先將當前字符串加入到池中,然後返回引用。

String s1 = "abc";
String s2 = new String("abc");
String s3 = s2.intern();
System.out.println(s1 ==s2); // false
System.out.println(s1 == s3); //true
7、字符串創建對象的問題

下面的代碼將創建幾個字符串對象。

String s1 = new String("Hello");  
String s2 = new String("Hello");

答案是3個對象.
第一,行1 字符串池中的“hello”對象。
第二,行1,在堆內存中帶有值“hello”的新字符串。
第三,行2,在堆內存中帶有“hello”的新字符串。這裏“hello”字符串池中的字符串被重用。

String s = new String("abc");

上述語句可能會創建一個或兩個對象,當字符串常量池中已經存在了“abc",則只會創建一個new String對象;如果字符串池中不存在"abc",則會先在字符串池中創建"abc",再在堆中創建new String對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章