直接上圖:
堆和棧很好理解,這裏講下方法區
方法區通俗點理解就是虛擬機在完成類裝載操作後,將class文件中的常量池載入到內存中,並保存在方法區中,
方法區的好處:
常量池是爲了避免頻繁的創建和銷燬對象而影響系統性能,其實現了對象的共享。
例如字符串常量池,在編譯階段就把所有的字符串文字放到一個常量池中。
(1)節省內存空間:常量池中所有相同的字符串常量被合併,只佔用一個空間。
(2)節省運行時間:比較字符串時,==比equals()快。對於兩個引用變量,只用==判斷引用是否相等,也就可以判斷實際值是否相等。
以 MyTest下面的爲列:
1 String s1 = "Hello"; 2 String s2 = "Hello"; 3 String s3 = "Hel" + "lo"; 4 String s4 = "Hel" + new String("lo"); 5 String s5 = new String("Hello"); 6 String s6 = s5.intern(); 7 String s7 = "H"; 8 String s8 = "ello"; 9 String s9 = s7 + s8; 10 11 System.out.println(s1 == s2); // true 12 System.out.println(s1 == s3); // true 13 System.out.println(s1 == s4); // false 14 System.out.println(s1 == s9); // false 15 System.out.println(s4 == s5); // false 16 System.out.println(s1 == s6); // true
在虛擬機接收到指令,首先會從classPath 中加載這個MyTest.class ,讀取這個文件的二進制,然後把Appmain類的類信息存放到運行時數據區的方法區中。這一過程稱爲MyTest類的加載過程。
在解釋上面的以前我們來回來一個經常的面試題
String a = "str" 和 String b = new String(“str”) , a == b ?
上面的答案是 flase ,爲什麼呢?
== 比較的是棧中的引用地址
1.String a = "str" ------------ 首先虛擬機會從方法區中去尋找是否有,有的話就直接把地址賦值給a ,沒有的話,就在方法區中開闢一個內存在存儲.(方法區的回收不會那麼頻繁,只有當內存不夠的時候纔會銷燬不用的常量,非靜態的)
2.String b = new String("str) 他是直接在堆內存中,直接開闢一個內存來存儲的,把地址給 b
所以 a == b = false
看過上面的現在講解下
s1 , s2 因爲是在加載的時候,內容都一樣所以肯定相等
s1 == s3這個地方有個坑,s3雖然是動態拼接出來的字符串,但是所有參與拼接的部分都是已知的字面量,在編譯期間,這種拼接會被優化,編譯器直接幫你拼好,因此String s3 = "Hel" + "lo";在class文件中被優化成String s3 = "Hello",所以s1 == s3成立。只有使用引號包含文本的方式創建的String對象之間使用“+”連接產生的新對象纔會被加入字符串池中
s1 == s4當然不相等,s4雖然也是拼接出來的,但new String("lo")這部分不是已知字面量,是一個不可預料的部分,編譯器不會優化,必須等到運行時纔可以確定結果,結合字符串不變定理,鬼知道s4被分配到哪去了,所以地址肯定不同。對於所有包含new方式新建對象(包括null)的“+”連接表達式,它所產生的新對象都不會被加入字符串池中。
配上一張簡圖理清思路:
s1 == s9也不相等,道理差不多,雖然s7、s8在賦值的時候使用的字符串字面量,但是拼接成s9的時候,s7、s8作爲兩個變量,都是不可預料的,編譯器畢竟是編譯器,不可能當解釋器用,不能在編譯期被確定,所以不做優化,只能等到運行時,在堆中創建s7、s8拼接成的新字符串,在堆中地址不確定,不可能與方法區常量池中的s1地址相同。
s4 == s5已經不用解釋了,絕對不相等,二者都在堆中,但地址不同。
s1 == s6這兩個相等完全歸功於intern方法,s5在堆中,內容爲Hello ,intern方法會嘗試將Hello字符串添加到常量池中,並返回其在常量池中的地址,因爲常量池中已經有了Hello字符串,所以intern方法直接返回地址;而s1在編譯期就已經指向常量池了,因此s1和s6指向同一地址,相等。
總結:
在理解方法區的時候,我們要從加載類的理解去理解區分於運行時
借鑑的文章:
https://www.cnblogs.com/syp172654682/p/8082625.html
https://blog.csdn.net/qq_41675686/article/details/80400775