JAVA基础5——与String相关的系列(1)
與String相關的系列
String, 是JAVA中常見的一個引用類型,且其具有一定的特殊性。
String類型被設置為final型,即不可繼承,也就不可修改其中的實現。
String可以改變嗎
String被設置為final型的,通常情況下是不可以改變的。
但是,從源碼中可以得知,其字符串存儲的時候使用的是char[],雖然被標識為final型,但是可以通過反射等方式修改其中的值,但是不推薦。
反射 修改字符串實際值的步驟 :
詳細可以參考下http://www.cnblogs.com/fguozhu/articles/2661055.html,講解的非常詳細。
關于JAVA虛擬機中的字符串常量池
在JAVA虛擬機(JVM)中存在著一個字符串池,其中保存著很多String對象,并且可以被共享使用,因此它提高了效率。由于String類是final的,它的值一經創建就不可改變,因此我們不用擔心String對象共享而帶來程序的混亂。字符串池由String類維護,我們可以調用intern()方法來訪問字符串池。
以String s = "abc"為例,這行代碼被執行的時候,JAVA虛擬機首先在字符串池中查找是否已經存在了值為"abc"的這么一個對象,它的判斷依據是String類equals(Object obj)方法的返回值。如果有,則不再創建新的對象,直接返回已存在對象的引用;如果沒有,則先創建這個對象,然后把它加入到字符串池中,再將它的引用返回。
對于字符串是否會進入常量池中:
常量池的內存模型介紹
關于詳細介紹,看下下面幾個介紹,講解的非常詳細,也很透徹:
http://www.jianshu.com/p/4ee6aec39c89?from=groupmessage
http://blog.csdn.net/zhushuai1221/article/details/52663818
http://blog.csdn.net/baidu_31657889/article/details/52315902
要點闡述如下:
字符串創建與存儲機制
這種情況下, 首先會到常量池中查找下是否已經存在相同內容的字符串,如果有的話,則直接將變量s指向常量池中已經存在的字符串上面。
這種情況下, 首先會判斷下倡廉吃中是否有相同值得字符串,如有,則拷貝一份到Heap中,然后返回heap中的地址;如果常量池中不存在,則會直接在heap中創建一份,然后將heap地址返回。
此處注意一點,就是如果"xxx"不存在與常量池中的話,也會先在常量池中創建一個(因為參數也是個字符串,下面章節中有講)。
關于String的intern()方法
講完上面的創建存儲機制,不得不提及一個不常用的intern()方法。這個方法的作用是,在常量池中查找是否有與當前字符串值相同的常量,如果沒有,則新建常量并返回常量引用,但當前引用不變;如果有直接返回引用。intern()方法的設計初衷就是重用String對象,進而可以節省內存消耗。
先看下下面這個代碼:
String str1 = new String("SEU")+ new String("Calvin"); System.out.println(str1.intern() == str1); System.out.println(str1 == "SEUCalvin"); 執行結果: true trueString str2 = "SEUCalvin";//新加的一行代碼,其余不變 String str1 = new String("SEU")+ new String("Calvin"); System.out.println(str1.intern() == str1); System.out.println(str1 == "SEUCalvin"); 執行結果: false false上面兩段代碼,看似str2與其余的沒有任何關系,卻影響到了str1的輸出結果。這個實際上與intern()方法有關系。intern()方法在JDK1.6中的作用是:比如String s = new String("SEU_Calvin"),再調用s.intern(),此時返回值還是字符串"SEU_Calvin",表面上看起來好像這個方法沒什么用處。但實際上,在JDK1.6中它做了個小動作:檢查字符串池里是否存在"SEU_Calvin"這么一個字符串,如果存在,就返回池里的字符串;如果不存在,該方法會把"SEU_Calvin"添加到字符串池中,然后再返回它的引用。
intern()方法在JDK1.7或者1.8版本中的作用是:比如String s3 = new String("1") + newString("1"),此時s3對象對應的內存內容“11”存儲在Heap區域,此時常量池中并無字符串11, 執行intern()方法的時候,先去常量池中看下11是否已經存在,如果不存在的話則直接將引用指向Heap中“11”字符串的地址。(這個地方是JDK7以上版本與JDK6的差別所在,即JDK6如果發現常量池中不存在,則會在常量池中創建一份,而JDK7或者JDK8中,如果常量池中沒有,則直接將引用指向Heap中已有的字符串對象,而不會重新創建, 因此s3 == s3.intern(),而這個在JDK6中是false的)
轉載于:https://www.cnblogs.com/veezean/p/7662398.html
總結
以上是生活随笔為你收集整理的JAVA基础5——与String相关的系列(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决git提交时报“there are
- 下一篇: 搭建DNS服务