首頁 > 軟體

Java 關於String字串原理上的問題

2022-04-07 19:01:19

1、String 是最基本的資料型別嗎?

不是。

Java 中的基本資料型別只有 8 個 :byte、short、int、long、float、double、char、boolean;除了基本型別,剩下的都是參照型別,Java 5 以後引入的列舉型別也算是一種比較特殊的參照型別。

2、字元型常數和字串常數的區別?

  • 形式上: 字元常數是單引號引起的一個字元,字串常數是雙引號引起的若干個字元;
  • 含義上: 字元常數相當於一個整型值( ASCII 值),可以參加表示式運算;字串常數代表一個地址值(該字串在記憶體中存放位置,相當於物件;
  • 佔記憶體大小:字元常數只佔 2 個位元組;字串常數佔若干個位元組(至少一個字元結束標誌) (注意: char 在Java中佔兩個位元組)。

3、什麼是字串常數池?

字串常數池:jvm為了提升效能和減少記憶體開銷,避免字元的重複建立,其維護了一塊特殊的記憶體空間,即字串常數池。當需要使用字串時,先去字串常數池中檢視該字串是否已經存在,如果存在,則可以直接使用,如果不存在,初始化,並將該字串放入字串常數池中。

所處位置說明

  • 在jdk6中,常數池的位置在永久代(方法區)中,此時常數池中儲存的是物件。
  • 在jdk7中,常數池的位置在堆中,此時,常數池儲存的就是參照了。
  • 在jdk8中,永久代(方法區)被元空間取代了。

4、String str=new String(「aaa」)建立了幾個物件?

1個或者2個

  • 第一種情況:字串常數池中已經有了 "aaa" 字串常數了,那麼此時會在堆中通過 new String()方法 建立 1 個字串物件。
  • 第二種情況:那就是字串常數池中沒有 "aaa" 字串常數了,此時會建立 2 個物件。首先 "aaa" 該表示式會檢視字串常數池中是否含有 "aaa" 常數,如果沒有的話,那麼在字串常數池中就會生成一個值為 "aaa" 的字串常數,然後再在堆中通過 new String()方法 建立一個值為 "aaa" 的物件。

5、字串的 intern 方法的執行過程是怎樣的?

你學 Java 的別這個高頻知識點都不知道呀,不知道的趕緊偷摸補一下。

在解析這個問題之前,我們先來做個題目:

public class Test {
    public static void main(String[] args) {
        String s = new String("2");
        s.intern();
        String s1 = "2";
        System.out.println(s == s1);

        String s3 = new String("3") + new String("3");
        s3.intern();
        String s4 = "33";
        System.out.println(s3 == s4);
    }
}

輸出結果

//jdk6

false

false

//jdk7

false

true

intern 方法在JDK1.6以前 和 JDK1.7以後有不同的處理:

  • 在JDK1.6中,intern 的處理是 先判斷字串常數是否在字串常數池中,如果存在直接返回該常數,如果沒有找到,則將該字串常數加入到字串常數區,也就是在字串常數區建立該常數;
  • 在JDK1.7中,intern 的處理是 先判斷字串常數是否在字串常數池中,如果存在直接返回該常數,如果沒有找到,說明該字串常數在堆中,則處理是把堆區該物件的參照加入到字串常數池中,以後別人拿到的是該字串常數的參照,實際存在堆中。

6、String,StringBuffer,StringBuilder 的區別是什麼?

可變與不可變

String

// 原始碼
private final char value[];

String 類中使用字元陣列儲存字串,因為有 「final」 修飾符,所以 String 物件是不可變的。對於已經存在的 String 物件的修改都是重新建立一個新的物件,然後把新的值儲存進去。

StringBufferStringBuilder

// 原始碼
char[] value;

StringBufferStringBuilder 都繼承自 AbstractStringBuilder 類,在 AbstractStringBuilder 中也是使用字元陣列儲存字串,這兩種物件都是可變的。

是否多執行緒安全

  • String 中的物件是不可變的,也就可以理解為常數,顯然執行緒安全。
  • StringBuilder 是非執行緒安全的。
  • StringBuffer 對方法加了同步鎖或者對呼叫的方法加了同步鎖,所以是執行緒安全的。
// StringBuffer 的追加操作
public synchronized StringBuffer append(StringBuffer sb) {
     toStringCache = null;
     super.append(sb);
     return this;
 }

效能

  • 每次對 String 型別進行改變的時候,都會生成一個新的 String 物件,然後將指標指向新的 String 物件。
  • StringBuffer 每次都會對 StringBuffer 物件本身進行操作,而不是生成新的物件並改變物件參照。相同情況下使用 StringBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的效能提升,但卻要冒多執行緒不安全的風險。

7、String為什麼要設計成不可變的?

  • 便於實現字串常數池。
  • 使多執行緒安全
  • 避免安全問題:在網路連線和資料庫連線中字串常常作為引數,例如,網路連線地址 URL,檔案路徑path,反射機制所需要的String引數。其不可變性可以保證連線的安全性。如果字串是可變的,駭客就有可能改變字串指向物件的值,那麼會引起很嚴重的安全問題。
  • 加快字串處理速度:由於String是不可變的,保證了hashcode的唯一性,於是在建立物件時其hashcode就可以放心的快取了,不需要重新計算。這也就是Map喜歡將String作為Key的原因。

到此這篇關於Java 關於String字串原理上的問題的文章就介紹到這了,更多相關Java String內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com