為什麼Java要把字元串設計成不可變的

来源:http://www.cnblogs.com/8hao/archive/2016/03/08/5253981.html
-Advertisement-
Play Games

原文出處: Hollis(@Hollis_Chuang) String是Java中一個不可變的類,所以他一旦被實例化就無法被修改。不可變類的實例一旦創建,其成員變數的值就不能被修改。不可變類有很多優勢。本文總結了為什麼字元串被設計成不可變的。將涉及到記憶體、同步和數據結構相關的知識。 字元串池 字元串


原文出處: Hollis(@Hollis_Chuang)

String是Java中一個不可變的類,所以他一旦被實例化就無法被修改。不可變類的實例一旦創建,其成員變數的值就不能被修改。不可變類有很多優勢。本文總結了為什麼字元串被設計成不可變的。將涉及到記憶體、同步和數據結構相關的知識。

字元串池

字元串池是方法區中的一部分特殊存儲。當一個字元串被被創建的時候,首先會去這個字元串池中查找,如果找到,直接返回對該字元串的引用。

下麵的代碼只會在堆中創建一個字元串

1 2 String string1 = "abcd"; String string2 = "abcd";

下麵是圖示:

string

如果字元串可變的話,當兩個引用指向指向同一個字元串時,對其中一個做修改就會影響另外一個。(請記住該影響,有助於理解後面的內容)

緩存Hashcode

Java中經常會用到字元串的哈希碼(hashcode)。例如,在HashMap中,字元串的不可變能保證其hashcode永遠保持一致,這樣就可以避免一些不必要的麻煩。這也就意味著每次在使用一個字元串的hashcode的時候不用重新計算一次,這樣更加高效。

在String類中,有以下代碼:

1 private int hash;//this is used to cache hash code.

以上代碼中hash變數中就保存了一個String對象的hashcode,因為String類不可變,所以一旦對象被創建,該hash值也無法改變。所以,每次想要使用該對象的hashcode的時候,直接返回即可。

使其他類的使用更加便利

在介紹這個內容之前,先看以下代碼:

1 2 3 4 5 6 7 HashSet<String> set = new HashSet<String>(); set.add(new String("a")); set.add(new String("b")); set.add(new String("c"));   for(String a: set)     a.value = "a";

在上面的例子中,如果字元串可以被改變,那麼以上用法將有可能違反Set的設計原則,因為Set要求其中的元素不可以重覆。上面的代碼只是為了簡單說明該問題,其實String類中並沒有value這個欄位值。

安全性

String被廣泛的使用在其他Java類中充當參數。比如網路連接、打開文件等操作。如果字元串可變,那麼類似操作可能導致安全問題。因為某個方法在調用連接操作的時候,他認為會連接到某台機器,但是實際上並沒有(其他引用同一String對象的值修改會導致該連接中的字元串內容被修改)。可變的字元串也可能導致反射的安全問題,因為他的參數也是字元串。

代碼示例:

1 2 3 4 5 6 7 boolean connect(string s){     if (!isSecure(s)) { throw new SecurityException(); }     //如果s在該操作之前被其他的引用所改變,那麼就可能導致問題。       causeProblem(s); }

不可變對象天生就是線程安全的

因為不可變對象不能被改變,所以他們可以自由地在多個線程之間共用。不需要任何同步處理。

總之,String被設計成不可變的主要目的是為了安全和高效。所以,使String是一個不可變類是一個很好的設計。

問啊-定製化IT教育平臺,牛人一對一服務,有問必答,開發編程社交頭條 官方網站:www.wenaaa.com 下載問啊APP,參與官方懸賞,賺百元現金。

QQ群290551701 聚集很多互聯網精英,技術總監,架構師,項目經理!開源技術研究,歡迎業內人士,大牛及新手有志於從事IT行業人員進入!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Windows平臺:Flume學習應用—Java寫日誌數據到MongoDB。
  • javaI/O流可根據流向分為輸入和輸出流,根據流數據類型可分為字元流和位元組流。 下麵用一張圖展示I/O流的劃分: 特點: 位元組流:讀到一個位元組就返回一個位元組,並且可以處理諸如MP3,avi,jpg等格式的文件。 字元流:讀到位元組時先按照編碼規則轉化,然後輸出。只能處理純文本數據。 節點流: 類型
  • 1.命名規範 本系列的第一篇,命名風格本就是有關藝術審美,沒有美與醜的絕對標準,本文難免帶有主觀選擇傾向,但是會儘量保持客觀的態度歸納幾種主流的命名風格,僅供參考。制定規範是為了方便團隊溝通和利於代碼維護,雖然並不能符合每個藝術家的胃口。對於獨立開發者,花點時間設計自己的編碼風格也是有助於提高能力的
  • 參考站點:http://www.iteye.com/problems/64517 方法executeUpdate 用於執行 INSERT、UPDATE 或 DELETE 語句以及 SQL DDL(數據定義語言)語句,例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE
  • Java反射機制是Java語言被視為準動態語言的關鍵性質。Java反射機制的核心就是允許在運行時通過Java Reflection APIs來取得已知名字的class類的相關信息,動態地生成此類,並調用其方法或修改其域(甚至是本身聲明為private的域或方法)。 也許你使用Java已經很長時間了,
  • import java.sql.*; public class TestJDBC { // orcl為oracle資料庫中的資料庫名,localhost表示連接本機的oracle資料庫 // 1521為連接的埠號 private static String url = "jdbc:oracle:t...
  • 在進行頁面提交的時候有2中方法 1: 直接<input type="submit" value="提交" name="submit"> 2: 通過js進行提交 <input type="button" id="tijiao " onclick="Dosave()">//這個地方對id不能用特殊字元
  • 譯文出處: 張洪亮 原文出處:Java Papers 本文將介紹Java中Integer的緩存相關知識。這是在Java 5中引入的一個有助於節省記憶體、提高性能的功能。首先看一個使用Integer的示例代碼,從中學習其緩存行為。接著我們將為什麼這麼實現以及他到底是如何實現的。你能猜出下麵的Java程式
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...