1. 什么是常量池
常量池可以分為兩類:靜態(tài)常量池和運行時常量池
-
靜態(tài)常量池:通常是指在編譯時期被確定祟印,并被保存在已經(jīng)編譯好的.class文件中的一些數(shù)據(jù)。編譯好的class 文件中粟害,從開頭依次是4個字節(jié)的magic number缚去,4個字節(jié)的存儲版本號带迟,然后就是存放常量的常量池,常量池的入口是constant_pool_count容量計數(shù)值。其中主要存放兩大類常量字面量Literal和符號引用兩 Symbolic Reference喉酌。
- 字面量:文本字符串菩貌,聲明為final常量值
- 符號引用量:包括類和接口的全限定名讽膏,字段名稱和描述符粥烁,方法名稱和描述符
運行時常量池:此時JVM加載類class文件后,會將常量池的內(nèi)容進入JVM的方法區(qū)中的運行時常量池進行存放留荔。運行時常量池的特點在于:具有動態(tài)性吟孙,在運行期間可以將新的常量放入池中,比如String類的intern()方法聚蝶。
2. 為什么需要常量池
- 常量池可以避免頻繁創(chuàng)建和銷毀對象而影響系統(tǒng)的性能杰妓,實現(xiàn)某些對象的共享,節(jié)省內(nèi)存空間碘勉。
3. String類與常量池
- 注意s5巷挥,因為拼接的時候ss作為變量,作為新字符串验靡,它是在堆中的倍宾,因此與s1地址是不同的
String s1 = "abcdefg";
String s2 = "abc"+"defg";
String s3 = new String("abcdefg");
String s4 = s2;
String ss ="defg";
String s5 = "abc"+ss;
System.out.println(s1 == s2); //true
System.out.println(s1 == s3); //false
System.out.println(s1 == s4); //ture
System.out.println(s1 == s5); //false
- String intern() 方法:查找常量池中是否存在equal的字符串,如果有的話返回該字符串的引用胜嗓,如果沒有則添加自己的字符串到常量池高职。
4. 基本類型包裝類與常量池
- Byte,Short辞州,Integer初厚,Long,Character孙技,Boolean中有實現(xiàn)常量池的技術(shù),這些包裝類默認創(chuàng)建了【-128排作,127】相應(yīng)類型的緩存數(shù)據(jù)牵啦,如果超出此范圍仍然會創(chuàng)建新的對象。注意基本類型的包裝類是類對象妄痪,因此創(chuàng)建的基本類型包裝類實例變量是引用變量哈雏,在緩存區(qū)范圍內(nèi)的是引用常量池地址,而在緩存區(qū)之外的引用的則是堆中對象地址。
Integer i1 = 10;
Integer i2 = 10;
Integer i3 = 300;
Integer i4 = 300;
System.out.println(i1==i2); // true
System.out.println(i3 ==i4);// false
- 基本類型與包裝類的比較時會自動拆箱成相應(yīng)基本類型裳瘪,對值進行比較
int i =40;
Integer i5 = new Integer(40);
System.out.println(i==i5);//true