byte數組轉字元串java:java byte轉string亂碼

一、String基礎

1、創建字元串方式

  1. String test = “abc”;
  2. String test = new String(“abc”);

2、String類是不可變的

吃透Java基礎十三:String字元串
  • String類被final關鍵字修飾,意味著String類不能被繼承,並且它的成員方法都默認為final方法;字元串一旦創建就不能再修改。
  • String實例的值是通過字元數組實現字元串存儲的。

String類不可變的好處?

  • 作為HashMap的鍵:因為String是不可變的,當創建String的時候哈希嗎已經計算好了,所以每次在使用字元串的哈希碼的時候就不用再計算一次,更高效。
  • 線程安全:因為字元串是不可變的,所以一定是線程安全的,不用考慮多線程訪問加鎖的情況。
  • 字元串常量池的需要。

3、String類常用方法

  • int length():返回字元串的長度。
吃透Java基礎十三:String字元串
  • int indexOf(int ch, int fromIndex) / int indexOf(String str, int fromIndex):該字元串中查找從fromIndex開始第一次出現ch字元/str字元串的位置。
吃透Java基礎十三:String字元串
  • int lastIndexOf(int ch, int fromIndex) / int lastIndexOf(String str, int fromIndex):查找ch字元/str字元串在該字元串最後一次出現的位置。
吃透Java基礎十三:String字元串
  • String substring(int beginIndex, int endIndex):截取從beginIndex(包含)到endIndex(不包含)的字元串。
吃透Java基礎十三:String字元串
  • String trim():去除字元串中的前後空格
吃透Java基礎十三:String字元串
  • boolean equals(Object anObject):重寫Object中的equals方法,字元串相同則返回true。
吃透Java基礎十三:String字元串
  • String toLowerCase():將字元串轉換為小寫。
吃透Java基礎十三:String字元串
  • String toUpperCase():將字元串轉換為大寫。
吃透Java基礎十三:String字元串
  • char charAt(int index):獲取字元串中指定位置的字元。
吃透Java基礎十三:String字元串
  • String[] split(String regex, int limit):將字元串分割為子字元串,返回字元串數組。
吃透Java基礎十三:String字元串
  • String replace(char oldChar, char newChar):把字元串序列中的oldChar替換為newChar。
吃透Java基礎十三:String字元串
  • byte[] getBytes():將該字元串轉為byte數組。
吃透Java基礎十三:String字元串

二、String高級

1、字元串常量池

字元串的分配和其他對象分配一樣,是需要消耗高昂的時間和空間的,而且字元串使用的非常多。JVM為了提高性能和減少內存的開銷,在實例化字元串的時候進行了一些優化:使用字元串常量池。每當創建字元串常量時,JVM會首先檢查字元串常量池,如果該字元串已經存在常量池中,那麼就直接返回常量池中的實例引用。如果字元串不存在常量池中,就會實例化該字元串並且將其放到常量池中。由於String字元串的不可變性,常量池中一定不存在兩個相同的字元串。

字元串常量池在jdk1.7之前是存在方法去的,從1.7之後放到堆裡面了。

2、String test = “abc”和new String(“abc”)區別

String test = “abc”:首先檢查字元串常量池中是否存在此字元串,如果存在則直接返回字元串常量池中字元串的引用,如果不存在則添加此字元串進常量池然後返回此引用。

new String(“abc”):直接在堆中創建字元串返回新創建字元串的引用,每次創建都是一個新的對象。

如下例子:

吃透Java基礎十三:String字元串

3、intern()方法

直接使用雙引號創建出來的String對象會直接存儲在字元串常量池中,new創建的的String對象,可以使用String提供的intern方法。intern 方法是一個native方法,intern方法會從字元串常量池中查詢當前字元串是否存在,如果存在,就直接返回當前字元串;如果不存在就會將當前字元串放入常量池中,之後再返回。

如下例子:

吃透Java基礎十三:String字元串

4、+字元串拼接

使用「+」拼接字元串時,JVM會隱式創建StringBuilder對象,每一個拼接就會隱式創建一個StringBuilder對象,當大量字元串拼接時,就會有大量StringBuilder在堆內存中創建,肯定會造成效率的損失,所以一般大量字元串拼接建議用StringBuilder(線程不安全)或StringBuffer(線程安全)。

如下例子看一下兩者效率:

吃透Java基礎十三:String字元串

運行輸出:

吃透Java基礎十三:String字元串

從結果我們可以看到,10萬次字元串的拼接用「+」的方式耗時13684毫秒,而StringBuilder拼接的話耗時1毫秒,效率是顯而易見的。

當”+”兩端均為編譯期確定的字元串常量時,編譯器會進行相應的優化,直接將兩個字元串常量拼接好

看如下例子:

吃透Java基礎十三:String字元串

編譯後class文件如下:

吃透Java基礎十三:String字元串

可見拼接的兩個字元串如果是常亮則直接在編譯器合併優化。

吃透Java基礎十三:String字元串

5、StringBuilder和StringBuffer拼接字元串

StringBuilder為了解決使用」+「大量拼接字元串時產生很多中間對象問題而提供的一個類,提供append和add方法,可以將字元串添加到已有序列的末尾或指定位置,實際上底層都是利用可修改的char數組(JDK 9 以後是 byte數組)來存儲的,當前容量不足時觸發擴容機制。

StringBuffer和StringBuilder的機制一樣,唯一不同點是StringBuffer內部使用synchronized關鍵字來保證線程安全,保證線程安全不可避免的產生了一些額外的開銷,如果不要求線程安全的情況下還是建議優先使用StringBuilder。

StringBuilder和StringBuffer都是繼承AbstractStringBuilder抽象類,裡面實現了字元串拼接的具體邏輯,我們來看一下:

吃透Java基礎十三:String字元串

數據都是保存在char[]裡面,當容量不足時進行數組的擴容:

吃透Java基礎十三:String字元串

從源碼可以看到,當需要容量不足時觸發擴容機制,擴容為原來的2倍+2的容量,最大數組擴容容量為:MAX_ARRAY_SIZE = Integer.MAX_VALUE – 8,Integer.MAX_VALUE為2的31次方-1。擴容完後把老的數組裡面的數據拷貝到新的數組裡面。

6、String字元串長度限制

要回答這個問題要分兩個階段看,分別是編譯期和運行期。不同的時期限制不一樣。

編譯期

我們所能想到的是String源碼中定義,存儲String字元的char數組最大是Integer.MAX_VALUE為2的31次方-1,那麼也就是說可以存儲2147483647個字元,分析到這時是不是以為大功告成了,其實不然,我們忽略了一點。

我們編譯java文件為class文件的時候是把字元串放在class的常量池中的,JVM對常量池的容量有嚴格的限制,JVN規定,字元串是由CONSTANTUtf8info類型的結構,CONSTANTUtf8_info的定義如下:

吃透Java基礎十三:String字元串

其中u1、u2是無符號的分別代表1個位元組和2個位元組,那麼我們只需要看length最多允許兩個位元組的長度,因此理論上允許的的最大長度是2^16=65536。而 java class 文件是使用一種變體UTF-8格式來存放字元的,null 值使用兩個 位元組來表示,因此只剩下 65536- 2 = 65534個位元組。

所以,在Java中,所有需要保存在常量池中的數據,長度最大不能超過65535,這當然也包括字元串的定義。

運行期

上面提到的這種String長度的限制是編譯期的限制,也就是使用String str= “”;這種字面值方式定義的時候才會有的限制。

String在運行期的限制,其實就是我們前文提到的那個Integer.MAX_VALUE ,這個值約等於4G,在運行期,如果String的長度超過這個範圍,就會拋出異常。

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/221568.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-09 13:12
下一篇 2024-12-09 13:12

相關推薦

發表回復

登錄後才能評論