眾所周知,在您生成相同源字符串的許多子字符串的情況下,Java會優化子字符串操作。 它通過使用(value, offset, count)
存儲信息的方式來做到這一點。 請參閱以下示例:
在上圖中,您會看到字符串“ Hello”和“ World!”。 源自“ Hello World!” 以及它們在堆中的表示方式:有一個包含“ Hello World!”的字符數組。 和兩個引用。 在某些情況下,例如對于標記化源文件的編譯器,這種存儲方法是有利的。 在其他情況下,這可能會導致您遇到OutOfMemorError(如果您常規地讀取長字符串并且僅保留其中的一小部分,但是上述機制會阻止GC收集原始的String緩沖區)。 有些甚至稱它為錯誤 。 我不會走那么遠,但這肯定是一個泄漏的抽象,因為您被迫執行以下操作以確保創建了副本: new String(str.substring(5, 6))
。
這一切都在2012年5月或Java 7u6中進行了更改。 鐘擺向后擺動,現在默認情況下會制作完整副本。 這對您意味著什么?
- 在大多數情況下,這只是Java瑣事中的一個不錯的片段
- 如果您正在編寫解析器等,則不能再依賴String提供的隱式緩存了。 您將需要基于緩沖和CharSequence的自定義實現來實現類似的機制
- 如果您正在執行
new String(str.substring)
來強制字符緩沖區的副本,則可以在更新到最新的Java 7時立即停止(并且由于Java 6處于EOLd狀態 ,因此您需要盡快這樣做) 說 )。
值得慶幸的是,Java的開發是一個開放的過程,并且這些信息在每個人的指尖!
與字符串相關的另外兩個引用(因為我們沒有說Java中的指針):
- 如果您要一遍又一遍地存儲相同的字符串(例如,您正在從套接字解析消息),則應閱讀String.intern()的替代方法 (并考慮閱讀第二版的《有效》,第50章)。 Java:避免使用其他類型更合適的字符串)
- 查看(并在使用它們之前做基準測試!)諸如UseCompressedStrings( 似乎已被刪除 ),UseStringCache和StringCache之類的選項
希望我沒有對您造成太大傷害,您發現這很有用! 直到下一次
–阿提拉·巴拉茲(Attila Balazs)
中繼:這篇文章是Java Advent Calendar的一部分,并根據Creative Commons 3.0 Attribution許可獲得許可。 如果您喜歡它,請通過共享,發推,FB,G +等來傳播信息! 想為博客寫文章嗎? 我們正在尋找能夠填補所有24個職位的貢獻者,并希望能為您貢獻力量! 聯系Attila Balazs貢獻力量!
參考:在Java Advent Calendar博客上,我們的JCG合作伙伴 Attila-Mihaly Balazs 對Java 7中的String.substring進行了更改 。
翻譯自: https://www.javacodegeeks.com/2012/12/changes-to-string-substring-in-java-7.html