日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JAVA基础5——与String相关的系列(1)

發布時間:2025/6/17 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JAVA基础5——与String相关的系列(1) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

與String相關的系列

String, 是JAVA中常見的一個引用類型,且其具有一定的特殊性。

String類型被設置為final型,即不可繼承,也就不可修改其中的實現。

String可以改變嗎

String被設置為final型的,通常情況下是不可以改變的。

但是,從源碼中可以得知,其字符串存儲的時候使用的是char[],雖然被標識為final型,但是可以通過反射等方式修改其中的值,但是不推薦。

反射 修改字符串實際值的步驟 :

  • 獲反射獲取到數組對應的字段Field
  • 修改器訪問屬性為可訪問
  • 修改其中的數組中的值。
  • 詳細可以參考下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)方法的返回值。如果有,則不再創建新的對象,直接返回已存在對象的引用;如果沒有,則先創建這個對象,然后把它加入到字符串池中,再將它的引用返回

    對于字符串是否會進入常量池中:

  • 如果是使用字面量的方式(即雙引號定義字符串)定義字符串,JVM執行時會首先去常量池中查找是否已經存在,如果存在就直接返回,如果不存在就在常量池中創建,并返回引用。
  • 如果是使用new String()的方式創建字符串,則必須手動調用intern()方法,才會去執行將內容放入常量池的操作(這個JDK6、7、8有著不同的實現邏輯,后面詳細介紹。)
  • 常量池的內存模型介紹

    關于詳細介紹,看下下面幾個介紹,講解的非常詳細,也很透徹:

    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

    要點闡述如下:

  • JDK6版本, 常量池放在Perm方法區,與Heap區完全獨立。
  • JDK7或者JDK8版本,常量池位于Heap區。
  • 字符串創建與存儲機制

  • 對于String s = "aaa" 直接雙引號的方式:
  • 這種情況下, 首先會到常量池中查找下是否已經存在相同內容的字符串,如果有的話,則直接將變量s指向常量池中已經存在的字符串上面。

  • 對于String s = new String("xxx")的方式:
  • 這種情況下, 首先會判斷下倡廉吃中是否有相同值得字符串,如有,則拷貝一份到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)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。