大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 學習攻略 java中string的不可變性詳解

java中string的不可變性詳解

更新時間:2019-09-04 10:51:24 來源:動力節點 瀏覽2610次

  

今天動力節點java培訓機構小編為大家分享“java中string的不可變性詳解”,希望通過此文能夠幫助大家,下面就隨小編一起看看java中string的不可變性詳解的內容吧。


一、java string 原理(為什么說String類是不可變的)


  1、什么是不可變對象


  如果一個對象在創建之后就不能再改變它的狀態,那么這個對象是不可變的(Immutable)。不能改變狀態的意思是,不能改變對象內的成員變量,包括基本數據類型變量的值不能改變,引用類型的變量不能指向其他的對象,引用類型指向的對象的狀態也不能改變。



  2、final關鍵字的作用


  如果要創建一個不可變對象,關鍵一步就是要將所有的成員變量聲明為final類型。所以下面簡單回顧一下final關鍵字的作用:


  final修飾類,表示該類不能被繼承,俗稱斷子絕孫類,該類的所有方法自動地成為final方法


  final修飾方法,表示子類不可重寫該方法


  final修飾基本數據類型變量,表示該變量為常量,值不能再修改


  final修飾引用類型變量,表示該引用在構造對象之后不能指向其他的對象,但該引用指向的對象的狀態可以改變



  3、String類不可變性的分析


  先看下面這段代碼:


String s = "abc";    //(1)

System.out.println("s = " + s);


s = "123";    //(2)

System.out.println("s = " + s);


打印結果為:


A.png


看到這里,你可能對String是不可變對象產生了疑惑,因為從打印結果可以看出,s的值的確改變了。其實不然,因為s只是一個String對象的引用,并不是String對象本身。


  當執行(1)處這行代碼之后,會先在方法區的運行時常量池創建一個String對象"abc",然后在Java棧中創建一個String對象的引用s,并讓s指向"abc",如下圖所示:


1.png

圖1


  當執行完(2)處這行代碼之后,會在方法區的運行時常量池創建一個新的String對象"123",然后讓引用s重新指向這個新的對象,而原來的對象"abc"還在內存中,并沒有改變,如下圖所示:


2.png

圖2


  4、String類不可變性的原理


  要理解String類的不可變性,首先看一下String類中都有哪些成員變量。在JDK1.8中,String的成員變量主要有以下幾個:


public final class String

    implements java.io.Serializable, Comparable<String>, CharSequence {

    /** The value is used for character storage. */

    private final char value[];


    /** Cache the hash code for the string */

    private int hash; // Default to 0


    /** use serialVersionUID from JDK 1.0.2 for interoperability */

    private static final long serialVersionUID = -6849794470754667710L;


    /**

     * Class String is special cased within the Serialization Stream Protocol.

     *

     * A String instance is written into an ObjectOutputStream according to

     * <a href="{@docRoot}/../platform/serialization/spec/output.html">

     * Object Serialization Specification, Section 6.2, "Stream Elements"</a>

     */

    private static final ObjectStreamField[] serialPersistentFields =

        new ObjectStreamField[0];


首先可以看到,String類使用了final修飾符,表明String類是不可繼承的。


  然后,我們主要關注String類的成員變量value,value是char[]類型,因此String對象實際上是用這個字符數組進行封裝的。再看value的修飾符,使用了private,也沒有提供setter方法,所以在String類的外部不能修改value,同時value也使用了final進行修飾,那么在String類的內部也不能修改value,但是上面final修飾引用類型變量的內容提到,這只能保證value不能指向其他的對象,但value指向的對象的狀態是可以改變的。通過查看String類源碼可以發現,String類不可變,關鍵是因為SUN公司的工程師,在后面所有String的方法里都很小心的沒有去動字符數組里的元素。所以String類不可變的關鍵都在底層的實現,而不僅僅是一個final。



  5、String對象真的不可變嗎


  上面提到,value雖然使用了final進行修飾,但是只能保證vaue不能指向其他的對象,但value指向的對象的狀態是可以改變的,也就是說,可以修改value指向的字符數組里面的元素。因為value是private類型的,所以只能使用反射來獲取String對象的value屬性,再去修改value指向的字符數組里面的元素。通過下面的代碼進行驗證:


String s = "Hello World";

System.out.println("s = " + s);


//獲取String類中的value屬性

Field valueField = String.class.getDeclaredField("value");


//改變value屬性的訪問權限

valueField.setAccessible(true);


//獲取s對象上的value屬性的值

char[] value = (char[]) valueField.get(s);


//改變value所引用的數組中的第6個字符

value[5] = '_';

System.out.println("s = " + s);


打印結果為:


s = Hello World

s = Hello_World


在上述代碼中,s始終指向同一個String對象,但是在反射操作之后,這個String對象的內容發生了變化。也就是說,通過反射是可以修改String這種不可變對象的。



二、設計目標(為什么String要設計成不可變的)


在Java中,將String設計成不可變的是綜合考慮到內存、同步、數據結構及安全等各種因素的結果,下文將為各種因素做一個小結。


1、運行時常量池的需要


String s = "abc";


  執行上述代碼時,JVM首先在運行時常量池中查看是否存在String對象“abc”,如果已存在該對象,則不用創建新的String對象“abc”,而是將引用s直接指向運行時常量池中已存在的String對象“abc”;如果不存在該對象,則先在運行時常量池中創建一個新的String對象“abc”,然后將引用s指向運行時常量池中創建的新String對象。


String s1 = "abc";

String s2 = "abc";


執行上述代碼時,在運行時常量池中只會創建一個String對象"abc",這樣就節省了內存空間。示意圖如下所示:


3.png

圖3



  2、同步


  因為String對象是不可變的,所以是多線程安全的,同一個String實例可以被多個線程共享。這樣就不用因為線程安全問題而使用同步。



  3、允許String對象緩存hashcode


  查看上文JDK1.8中String類源碼,可以發現其中有一個字段hash,String類的不可變性保證了hashcode的唯一性,所以可以用hash字段對String對象的hashcode進行緩存,就不需要每次重新計算hashcode。所以Java中String對象經常被用來作為HashMap等容器的鍵。



  4、安全性


  如果String對象是可變的,那么會引起很嚴重的安全問題。比如,數據庫的用戶名、密碼都是以字符串的形式傳入來獲得數據庫的連接,或者在socket編程中,主機名和端口都是以字符串的形式傳入。因為String對象是不可變的,所以它的值是不可改變的,否則黑客們可以鉆到空子,改變String引用指向的對象的值,造成安全漏洞。


以上就是動力節點java培訓機構小編介紹的java中string的不可變性詳解”的內容,希望對大家有幫助,更多精彩內容請繼續關注動力節點java培訓機構官網,每天會有精彩內容分享與你。


相關免費視頻教程推薦


java基礎視頻教程下載——String對象的不可變性:http://www.dabaquan.cn/xiazai/2514.html


提交申請后,顧問老師會電話與您溝通安排學習

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 日本不卡高清中文字幕免费 | 日本免费小视频 | 五月天在线婷婷 | 亚洲综合伦理 | 国产乱码精品一区二区三区卡 | 国产欧美另类性视频 | 99热爱 | 日韩第三页 | 在线黄色.com | 天天插夜夜爽 | 国产精品岛国久久久久 | 国产老熟 | 久久亚洲一区二区 | 国产一级特黄aaaa大片野外 | 成人看的一级毛片 | 美国免费三片在线观看 | 国产成人精品区在线观看 | 亚洲国产精品一区二区首页 | 黄色日比视频 | 综合久| 国产精品免费视频播放 | 青青免费视频精品一区二区 | 天天舔天天射天天干 | 99久久精品在免费线18 | 亚洲欧美视频二区 | 99久久国产综合色 | 亚洲欧洲日产国码天堂 | 久久www免费人成高清 | 亚洲视频中文字幕在线观看 | 欧美久久综合 | 欧美日韩免费做爰视频 | 青青青在线视频人视频在线 | 美女视频黄的全i免费 | 国产乱叫456在线 | 国产午夜精品一区二区 | 九九精品久久久久久久久 | 久久亚洲综合中文字幕 | 91手机在线观看 | 夜夜操天天插 | 成人日韩视频 | 亚洲一区二区三区在线视频 |