String字符串
java.lang.String
1、字符串的特點
1、字符串String類型本身是final聲明的,意味着我們不能繼承String。final類不能被繼承。
2、字符串的對象也是不可變對象,意味着一旦進行修改,就會產生新對象
字符串的對象也是不可變對象
我們修改了字符串後,如果想要獲得新的內容,必須重新接受。
如果程序中涉及到大量的字符串的修改操作,那麼此時的時空(時間、空間 )消耗比較高。可能需要考慮使用StringBuilder或StringBuffer。
3、String對象內部是用字符數組進行保存的
String對象底層的存儲
JDK1.9之前有一個char[] value數組,JDK1.9之後byte[]數組
JDK8 private final char value[];
JDK11 private final byte[] value;
4、String類中這個char[] values數組也是final修飾的,意味着這個數組不可變,然後它是private修飾,外部不能直接操作它,String類型提供的所有的方法都是用新對象來表示修改後內容的,所以保證了String對象的不可變。
5、就因爲字符串對象設計爲不可變,String對象不可變的特性,使得我們可以把一些字符串存到常量池中,字符串有常量池來保存很多常量對象
常量池在方法區。字符串有常量池。常量池中的是可以共享的。
字符串常量池在哪裏?Oracle官方虛擬機HotSpot
如果細緻的劃分:
(1)JDK1.6及其之前:方法區
(2)JDK1.7:堆 挪到堆中,即在堆中單獨劃分了一塊來存字符串常量
(3)JDK1.8:元空間 從堆中挪出,挪到一個“元空間meta space”,即類似於方法區。
String對象怎麼就不可變?
①底層char[]數組有final修飾,意味着這個數組不能擴容等,來達到存更多的字符。
②char[]數組是私有的,我們程序員無法直接操作這個char[]數組,而且String沒有提供這樣的方法,來修改char[]數組的元素的值。
String提供的所有的方法,對字符串的修改都是給你返回一個新的字符串對象。
保證了String對象的不可變。
public class TestString01 {
@Test
public void test02(){
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2);//true
String s3 = new String("hello");
String s4 = new String("hello");
System.out.println(s3 == s4 );//false
}
@Test
public void test01(){
String s1 = "hello";
System.out.println(s1);//hello
s1 = "world";
System.out.println(s1);//world
s1 = s1 + "java";
System.out.println(s1);//worldjava
String s = "";
System.out.println(s);//
change(s);
System.out.println(s);//
}
public void change(String str){
str = "hello";
}
}
簡單的String面試題
面試題:
Q1:String是最基本的數據類型嗎?
A:
不是,Java基本數據類型只有8種,byte、short、int、long、float、double、char、boolean。
String(確實最常用)
Q2:"String、StringBuilder、StringBuffer的區別是什麼?"
A2:
1、可變性。String不可變,StringBuilder與StringBuffer是可變的。
- String類中使用只讀字符數組保存字符串,private final char value[],所以是不可變的(Java 9 中底層把 char 數組換成了 byte 數組,佔用更少的空間)。
- StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字符數組保存字符串,char[]value,這兩種對象都是可變的。
可變性 String不可變 StringBuilder與StringBuffer是可變的
2、線程安全性。String和StrinbBuffer是線程安全的,StringBuilder是非線程安全的。
- String線程安全是因爲其對象是不可變的,StringBuffer線程安全是因爲對方法加了同步鎖或者對調用的方法加了同步鎖。
- StringBuilder並沒有對方法進行加同步鎖,所以是非線程安全的。
線程安全性 String和StringBuffer是線程安全的 StringBuilder是非線程安全的
3、性能。
- String的性能較差,因爲每次對String 類型進行改變的時候,都會生成一個新的String對象,然後將指針指向新的String 對象。
- 而StringBuffer/StringBuilder性能更高,是因爲每次都是對對象本身進行操作,而不是生成新的對象並改變對象引用。一般情況下StringBuilder 相比StringBuffer 可獲得10%~15% 左右的性能提升。
String StringBuilder StringBuffer
- 如果要操作少量的數據用String;
- 單線程操作字符串緩衝區下操作大量數據StringBuilder;
- 多線程操作字符串緩衝區下操作大量數據StringBuffer;
參考資料
記錄 - 搞定Java核心技術
高薪之路–Java面試題精選集
從Hello到goodbye