媽媽再也不用擔心我的面試之String類詳解
其實在java中String並不能算是一個基本型別,迴歸到String的本質其實在jdk1.8以前他是一個final修飾的char陣列,1.9以後他是一個final修飾的byte陣列;由開發者將其封裝成String類;其實我們也可以從程式碼中來證明String是一個類的事實:
public class String1 {
public static void main(String[] args) {
String string = "sss";
System.out.println("sss".equals(string));
}
}
true
這裡我們可以看到 "sss" 這個常量可以使用equals方法進行物件相等這個判斷,所以我們可以得出結論 沒有字串這個常量,有的只有String類的匿名物件。
這裡使用equals我們有一個小技巧,也就是把字串常量寫在前面:
public class String1 {
public static void main(String[] args) {
String input = null; //假設是一個輸入
System.out.println(input.equals("sss"));
}
}
Exception in thread "main" java.lang.NullPointerException
at String1.main(String1.java:5)
這裡我們使用者並沒有輸出,這樣我們在進行比較時候就會報錯, 但是如果我們
public class String1 {
public static void main(String[] args) {
String input = null; //假設是一個輸入
System.out.println("sss".equals(input));
}
}
將字串寫在前面,我們可以通過equals提供一個可以迴避null的判斷來避免錯誤,字串是一個匿名物件,只要是物件就會開闢堆記憶體空間,所以不會報錯。
現在我們來解釋一下字串的比較
我們先來看一下int型別的 == 判斷
public class String1 { public static void main(String[] args) { int x = 10; int y = 10; System.out.println(x == y); } }
這裡程式碼是對基本型別進行判斷。但是如果我們使用 == 進行String類的比較呢?
public class String1 {
public static void main(String[] args) {
String str1 = "ss";
String str2 = new String("ss");
System.out.println(str1 == str2);
}
}
false
首先我們避開程式碼不談,我們先來說一下這個new, new的功能其實就是在記憶體中開闢堆記憶體空間,所以說str2是重新開闢了一塊記憶體空間
所以說我們可以得出一個結論
“==” 用作數值的比較,但是如果用作物件的比較上則比較的記憶體的地址數值
現在我們就像判斷兩個物件的比較該怎麼辦。用equals這個類提供的方法,來直接對字串進行比較。
public class String1 {
public static void main(String[] args) {
String str1 = "ss";
String str2 = new String("ss");
System.out.println(str1.equals(str2));
}
}
true
下面我們在繼續看一段程式碼
public class String1 {
public static void main(String[] args) {
String str1 = "sss";
String str2 = "sss";
System.out.println(str1 == str2);
}
}
true
這裡我們發現執行結果返回的是true,所以我們可以判斷這裡指向的是他同一塊堆記憶體空間
主要原因是java底層提供一個專門的字串池(字串陣列)
str1會首先在在這個字串池中開闢一塊 "sss" 的堆記憶體空間
這時候我們再有一個str2的時候 他會優先查詢池 , 如果池中有這個資料則會優先使用池中資料,
如果沒有,則會在池中在開闢記憶體空間
對於字串而言在池中實現自動儲存,可以提升操作效能
public class String1 {
public static void main(String[] args) {
String str1 = new String("sss");
}
}
現在我們來看一下之前這段程式碼。基於我們上面的分析來看。"sss"其實就是一個匿名物件開闢一塊記憶體空間, 但是我們的關鍵字new的功能也會開闢一塊堆記憶體空間,我們只會使用一塊記憶體空間,所以由字串常量所定義的匿名物件就會成為垃圾空間。
總結:我們使用
public class String1 {
public static void main(String[] args) {
String str1 = "sss";
}
}
這種方式來進行會相對節約一部分記憶體的使用
接下來讓我們再次蹂躪我們之前的程式碼
public class String1 {
public static void main(String[] args) {
String str1 = "sss";
String str2 = new String("sss");
}
}
綜合來看我們的str1是使用我們java實現的字串池(也是堆記憶體)來進行儲存
str2 我們是使用new開闢的堆記憶體空間來儲存,
所以說我們的執行結果就是false
public class String1 {
public static void main(String[] args) {
String str1 = "sss";
String str2 = new String("sss");
System.out.println(str1 == str2);
}
}
綜合以上就是我瞭解的String方面的問題
==============================================================
補充一個Integer型別的== 判斷
public class String1 {
public static void main(String[] args) {
Integer a = 10;
Integer a1 = 10;
Integer b = 200;
Integer b1 = 200;
System.out.println(a == a1);
System.out.println(b == b1);
}
}
true
false
因為Integer : -127 +127 之前a a1 的值在這個區間 原始碼中Integer的區間定義是通過快取實現 ,b b1的比較直接從快取中取出,所以相同
但是b b1不在這個區間所以需要重新開闢不同的地址儲存,所以導致不同