“不可變的對象”與“不可變的對象引用”


什么是不可變的對象呢?我們都知道String是不可變的,如果有涉及大量的字符串拼接我們最好不要用String,雖然我們在代碼中可以這樣寫:

String str = "test";
str = "test1";

這樣寫是沒有錯的,這是不是和我們所說的String類型時不可變的違背了呢?其實不然,我們這里看到str“改變”了值,其實不是不是真正改變了,而是改變了str的引用。我們從下圖可以看到當定義String str = "test1"時,Java實際上做了這個操作(我們在這里不討論String關於使用new和不使用new,以及堆內存分配的問題)。

在我們再一次賦值str = "test1"時,Java實際上做了下面這個操作:

"test"變量其實並沒有改變,改變的只是str的引用,將str的引用重新指向在常量池中新創建的"test1"變量,這即是"不可變的對象"

那么何為"不可變的對象引用"呢?字面意思當然就是和上面相反,允許它改變str的引用重新指向"test1"字符串變量。即是在定義變量時加上final關鍵字。我們看以下代碼:首先有一個User類,這個類中的name變量是普通變量,可以通過setName方法賦值。

 1 package day_20_immutable;
 2 
 3 /**
 4  * @author 余林豐
 5  *
 6  * 2016年10月20日
 7  */
 8 public class User {
 9     private String name;
10 
11     public String getName() {
12         return name;
13     }
14 
15     public void setName(String name) {
16         this.name = name;
17     }
18 }

我們在main方法中來試驗一把final關鍵字的“不可變的對象引用”。

 1 package day_20_immutable;
 2 
 3 /**
 4  * @author 余林豐
 5  *
 6  * 2016年10月20日
 7  */
 8 public class Main {
 9     private final User user = new User();
10     /**
11      * @param args
12      */
13     public static void main(String[] args) {
14         Main main = new Main();
15         main.user.setName("keven");
16         System.out.println(main.user.getName());
17         main.user.setName("turbo");        //final關鍵字不影響本身是可改變的對象
18         System.out.println(main.user.getName());
19         
20         //main.user = new User();    //報錯,因為final關鍵字修飾的變量不能改變它的引用
21         
22     }
23 
24 }

以上便是“不可變對象”與“不可變的對象引用”的區別,為什么要區分這兩個概念,這是為后面Java多線程的線程安全先做下鋪墊。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM