缓冲池、String/StringBuffer/StringBuilder、intern()
1.緩沖池
1.1 new Integer(123) 與 Integer.valueOf(123) 的區(qū)別在于:
- new Integer(123) :每次都會(huì)新建一個(gè)對(duì)象
- Integer.valueOf(123) :會(huì)使用緩存池中的對(duì)象,多次調(diào)用會(huì)取得同一個(gè)對(duì)象的引用。
1.2?valueOf() 方法的實(shí)現(xiàn)
先判斷值是否在緩存池中,如果在的話就直接返回緩存池的內(nèi)容。
public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i); }1.3?在 Java 8 中,Integer 緩存池的大小默認(rèn)為 -128~127。
1.4 自動(dòng)裝箱
編譯器會(huì)在自動(dòng)裝箱過(guò)程調(diào)用 valueOf() 方法,因此多個(gè) Integer 實(shí)例使用自動(dòng)裝箱來(lái)創(chuàng)建并且值相同,那么就會(huì)引用相同的對(duì)象。
Integer m = 123; Integer n = 123; System.out.println(m == n); // true1.5?基本類型對(duì)應(yīng)的緩沖池如下:
- boolean values true and false
- all byte values
- short values between -128 and 127
- int values between -128 and 127
- char in the range \u0000 to \u007F
在使用這些基本類型對(duì)應(yīng)的包裝類型時(shí),就可以直接使用緩沖池中的對(duì)象。
2. String
2.1 概覽
String 被聲明為 final,因此它不可被繼承。
內(nèi)部使用 char 數(shù)組存儲(chǔ)數(shù)據(jù),該數(shù)組被聲明為 final,這意味著 value 數(shù)組初始化之后就不能再引用其它數(shù)組。
并且 String 內(nèi)部沒(méi)有改變 value 數(shù)組的方法,因此可以保證 String 不可變。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {/** The value is used for character storage. */private final char value[];...2.2?不可變的好處
2.2.1 可以緩存 hash 值
因?yàn)?String 的 hash 值經(jīng)常被使用,例如 String 用做 HashMap 的 key。
不可變的特性可以使得 hash 值也不可變,因此只需要進(jìn)行一次計(jì)算。
2.2.2 String Pool 的需要
如果一個(gè) String 對(duì)象已經(jīng)被創(chuàng)建過(guò)了,那么就會(huì)從 String Pool 中取得引用。
只有String 是不可變的,才可能使用 String Pool。
2.2.3 安全性
String 經(jīng)常作為參數(shù),String 不可變性可以保證參數(shù)不可變。
例如在作為網(wǎng)絡(luò)連接參數(shù)的情況下如果 String 是可變的,那么在網(wǎng)絡(luò)連接過(guò)程中,String 被改變,改String 對(duì)象的那一方以為現(xiàn)在連接的是其它主機(jī),而實(shí)際情況卻不一定是。
2.2.4 線程安全
String 不可變性天生具備線程安全,可以在多個(gè)線程中安全地使用。
3. String, StringBuffer and StringBuilder(詳細(xì)介紹)
3.1. 可變性
- String 不可變;
- StringBuffer 和 StringBuilder 可變。
3.2 線程安全
- String 不可變,因此是線程安全的;
- StringBuilder 不是線程安全的;
- StringBuffer 是線程安全的,內(nèi)部使用 synchronized 進(jìn)行同步。
3.3 String.intern()
使用 String.intern() 可以保證相同內(nèi)容的字符串變量引用同一的內(nèi)存對(duì)象。
下面示例中,s1 和 s2 采用 new String() 的方式新建了兩個(gè)不同對(duì)象,而 s3 是通過(guò) s1.intern() 方法取得一個(gè)對(duì)象引用。intern() 首先把 s1 引用的對(duì)象放到 String Pool(字符串常量池) 中,然后返回這個(gè)對(duì)象引用。因此 s3 和 s1 引用的是同一個(gè)字符串常量池的對(duì)象。
String s1 = new String("aaa"); String s2 = new String("aaa"); System.out.println(s1 == s2); // false String s3 = s1.intern(); System.out.println(s1.intern() == s3); // true System.out.println(s1 == s3); // false如果是采用 "bbb" 這種使用雙引號(hào)的形式創(chuàng)建字符串實(shí)例,會(huì)自動(dòng)地將新建的對(duì)象放入 String Pool 中。
String s4 = "bbb"; String s5 = "bbb"; System.out.println(s4 == s5); // true在 Java 7 之前,字符串常量池被放在運(yùn)行時(shí)常量池中,它屬于永久代。
而在 Java7,字符串常量池被移到 Native Method 中。這是因?yàn)橛谰么目臻g有限,在大量使用字符串的場(chǎng)景下會(huì)導(dǎo)致OutOfMemoryError 錯(cuò)誤。
?
總結(jié)
以上是生活随笔為你收集整理的缓冲池、String/StringBuffer/StringBuilder、intern()的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Web 页面请求过程
- 下一篇: Executor框架、ThreadPoo