一般的對象都是通過new
進(jìn)行創(chuàng)建的奕短,但是String
有兩種創(chuàng)建方式肄扎。
也就是我們常用的直接聲明的方式,比如String str="abc"
,通過直接量"abc"進(jìn)行賦值宽菜,這種方式是極力推薦的神凑。為什么呢净神?我們來看一個情況:
public class Client{
public static void main(String[] args){
String str1 = "a";
String str2 = "a";
String str3 = new String("a");
String str4 = str3.intern();
System.out.println(str1 == str2);
System.out.println(str1 == str3);
System.out.println(str1 == str4);
}
}
運(yùn)行結(jié)果:
??true
??false
??true
我們知道 "=="
是用來判斷了兩個對象是否為同一個對象的,"intern()"
方法是干嘛用的呢溉委?
原來在java里面為了避免在一個系統(tǒng)中大量產(chǎn)生String對象(為什么大量產(chǎn)生鹃唯,因為String字符串在程序中是最常用的類型),于是設(shè)計了一個字符串常量池
的東西.
和我們數(shù)據(jù)庫連接池的概念差不多瓣喊,當(dāng)我們采用直接聲明的方式而不是new
的方式創(chuàng)建字符串的時候坡慌,程序會首先檢查池中有沒有字面值和當(dāng)前聲明的字符串變量一樣的字符串,如果有就返回池中該對象的引用藻三,否則就創(chuàng)建這個字符串洪橘,然后把新對象投入池中,并返回新對象的引用棵帽。
"intern()"
方法所做的事情就是這樣的事情梨树,由于new
創(chuàng)建的對象,程序是不會主動去執(zhí)行這個操作的岖寞,所以我們手動執(zhí)行了下這個操作,于是就有了 str1 == str4
的返回值為true
你可能會問這樣做會不會有線程安全問題柜蜈?要不要考慮字符串常量池的垃圾回收問題仗谆?
???1. 其實 String
類型本身就是一個final
的類,所以不可能被繼承淑履,也就不可能出現(xiàn) String
的派生類了隶垮,其次 String
的方法如果是 String
的返回值,就會重新創(chuàng)建一個 String
對象秘噪,并不會對原來的對象進(jìn)行修改狸吞,這也就是String的不可變性
,既然都不可變了,就像常量一樣那么也就不存在什么線程安全問題了。
???2. 字符串常量池從編譯期開始就是存在于JVM的常量池中蹋偏,垃圾回收主要是回收堆區(qū)的內(nèi)存便斥,并不會回收常量池的東西。