摘要:我們都知道中的類的設(shè)計(jì)是不可變的,來(lái)看下類的源碼。其值也就是對(duì)字符數(shù)組的封裝,即,其值被定義成的,說(shuō)明不能通過外界修改,即不可變。真的不可變嗎來(lái)看下面這個(gè)例子。所以說(shuō),這里的字符串并不是可變,只是變更了字符串引用。
我們都知道 Java 中的 String 類的設(shè)計(jì)是不可變的,來(lái)看下 String 類的源碼。
public final class String implements java.io.Serializable, Comparable, 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 // ... }
可以看出 String 類是 final 類型的,String 不能被繼承。其值 value 也就是對(duì)字符數(shù)組的封裝,即 char[],其值被定義成 private final 的,說(shuō)明不能通過外界修改,即不可變。
String 真的 "不可變 " 嗎?來(lái)看下面這個(gè)例子。
String str = "Python"; System.out.println(str); // Python str = "Java"; System.out.println(str); // Java str = str.substring(1); System.out.println(str); // ava
你有可能會(huì)問:str 不是由 Python 變成 Java 了嗎?然后通過 substring 方法變成 ava 了嗎?
這其實(shí)是初學(xué)者的一個(gè)誤區(qū),從上面看 String 的結(jié)構(gòu)可以得知字符串是由字符數(shù)組構(gòu)成的,str 只是一個(gè)引用而已,第一次引用了 "Python",后面變成了 "Java",而 substring 也是用 Arrays.copyOfRange 方法重新復(fù)制字符數(shù)組構(gòu)造了一個(gè)新的字符串。
所以說(shuō),這里的字符串并不是可變,只是變更了字符串引用。
關(guān)于 substring 在 JDK 各個(gè)版本的差異可以看這篇文章《注意:字符串substring方法在jkd6,7,8中的差異》,也可以去看 substring 的各個(gè)版本的源碼。
String 真的真的真的 "不可變 " 嗎?上面的例子肯定是不可變的,下面這個(gè)就尷尬了。
String str = "Hello Python"; System.out.println(str); // Hello Python Field field = String.class.getDeclaredField("value"); field.setAccessible(true); char[] value = (char[])field.get(str); value[6] = "J"; value[7] = "a"; value[8] = "v"; value[9] = "a"; value[10] = "!"; value[11] = "!"; System.out.println(str); // Hello Java!!
通過反射,我們改變了底層的字符數(shù)組的值,實(shí)現(xiàn)了字符串的 “不可變” 性,這是一種騷操作,不建議這么使用,違反了 Java 對(duì) String 類的不可變?cè)O(shè)計(jì)原則,會(huì)造成一些安全問題。
是不是又漲姿勢(shì)了?分享給你的朋友們吧!更多干貨推薦
1.史上最強(qiáng) Java 中高級(jí)面試題整理
2.史上最強(qiáng) Spring Boot & Cloud 教程整理
3.史上最強(qiáng)架構(gòu)設(shè)計(jì)分布式技術(shù)干貨整理
更多請(qǐng)掃描下方的二維碼關(guān)注我們的微信公眾號(hào),干貨每日推送!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/77303.html
摘要:性能當(dāng)字符串是不可變時(shí),字符串常量池才有意義。字符串常量池的出現(xiàn),可以減少創(chuàng)建相同字面量的字符串,讓不同的引用指向池中同一個(gè)字符串,為運(yùn)行時(shí)節(jié)約很多的堆內(nèi)存。 在學(xué)習(xí)Java的過程中,我們會(huì)被告知 String 被設(shè)計(jì)成不可變的類型。為什么 String 會(huì)被 Java 開發(fā)者有如此特殊的對(duì)待?他們的設(shè)計(jì)意圖和設(shè)計(jì)理念到底是什么?因此,我?guī)е韵氯齻€(gè)問題,對(duì) String 進(jìn)行剖析: ...
摘要:方法可接收兩個(gè)參數(shù),第一個(gè)參數(shù)是分隔符,即用來(lái)分隔字符串的字符,默認(rèn)是所有的空字符,包括空格換行制表符等。拆分過程會(huì)消耗分隔符,所以拆分結(jié)果中不包含分隔符。 正如《你真的知道Python的字符串是什么嗎?》所寫,Python 中字符串是由 Uniocde 編碼的字符組成的不可變序列,它具備與其它序列共有的一些操作,例如判斷元素是否存在、拼接序列、切片操作、求長(zhǎng)度、求最值、求元素的索引位...
摘要:方法可接收兩個(gè)參數(shù),第一個(gè)參數(shù)是分隔符,即用來(lái)分隔字符串的字符,默認(rèn)是所有的空字符,包括空格換行制表符等。拆分過程會(huì)消耗分隔符,所以拆分結(jié)果中不包含分隔符。 正如《你真的知道Python的字符串是什么嗎?》所寫,Python 中字符串是由 Uniocde 編碼的字符組成的不可變序列,它具備與其它序列共有的一些操作,例如判斷元素是否存在、拼接序列、切片操作、求長(zhǎng)度、求最值、求元素的索引位...
閱讀 2514·2023-04-25 17:37
閱讀 1195·2021-11-24 10:29
閱讀 3701·2021-09-09 11:57
閱讀 698·2021-08-10 09:41
閱讀 2249·2019-08-30 15:55
閱讀 2817·2019-08-30 15:54
閱讀 1949·2019-08-30 15:53
閱讀 901·2019-08-30 15:43