一、什麼是Java Immutable
Java Immutable是指不可改變的對象,一旦創建之後就不能被改變。Immutable可以提高並發程序的安全性和性能,因為多個線程同時訪問不可變對象是安全的。
在Java中,有許多基礎類和常用工具類都是Immutable的,比如String、Integer、Double等基礎類。
示例代碼:
String str = "Hello World";
str = str + "!"; // 這裡實際上是創建了一個新的字符串對象,而原來的“Hello World”仍然不變
二、如何創建Java Immutable對象
Java中有多種方式可以創建Immutable對象,以下是其中較為常用的幾種:
1. 構造函數
在構造函數中初始化所有的屬性,並將所有屬性設置為final,這樣對象就無法被改變。
示例代碼:
public class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 省略 getter 方法
}
2. 靜態工廠方法
可以通過靜態工廠方法創建Immutable對象,這種方式比構造函數更加靈活。
示例代碼:
public class Color {
private int red;
private int green;
private int blue;
private Color(int r, int g, int b) {
red = r;
green = g;
blue = b;
}
public static Color fromRGB(int r, int g, int b) {
return new Color(r, g, b);
}
// 省略 getter 方法
}
三、Java Immutable的優缺點
1. 優點
a. 線程安全
Immutable對象在多線程環境下是安全的,因為它們不可變,沒有線程會修改它們。
b. 緩存Hash
Immutable對象通常都有一個緩存的hash值,這樣可以提高哈希表等數據結構的查找速度。
c. 合併效率高
如果需要合併多個Immutable對象,只需要創建一個新的Immutable對象,然後將舊的對象複製到新的對象中即可。
2. 缺點
a. 內存佔用較高
因為每次修改Immutable對象都需要創建一個新的對象,所以會佔用更多的內存。
b. 不易擴展
Immutable對象通常都是由多個final屬性組成的,如果需要添加或者刪除一個屬性,那麼就需要創建一個全新的對象。
四、Java Immutable的應用場景
Java Immutable適用於以下場景:
1. 大量重複字符串的場景
在大量重複字符串的場景下,可以使用String.intern()方法將字符串放入常量池中。
2. 多線程共享對象的場景
在多線程共享對象的場景下,採用Immutable對象可以避免因多線程修改同一個對象而導致的並發問題。
3. 數據庫連接等資源共享的場景
在共享類似數據庫連接等資源的場景下,使用Immutable對象可以保證資源安全不被多線程錯誤使用。
五、Java Immutable的注意事項
1. final屬性和對象引用的區別
Java中final屬性是指屬性的值無法被修改,而final對象引用則是指引用指向的對象無法改變。因此,如果一個對象是Immutable的,那麼它的所有屬性都應該是final的,但這不代表這個對象的引用也是final的。
示例代碼:
public class Car {
private final String name;
private final Engine engine;
public Car(String name, Engine engine) {
this.name = name;
this.engine = engine;
}
// 只有final修飾的name屬性才是不可變的,engine屬性指向的對象仍然是可以改變的
// 如果要把engine也設置為不可變,可以在Engine類中添加final屬性
}
2. 防禦性拷貝
在創建Immutable對象時,應該儘可能避免使用可變類型的屬性。如果必須使用可變類型的屬性,應該在構造函數中對屬性進行防禦性拷貝,以保證對象無法被外部修改。
示例代碼:
public class Book {
private final String title;
private final List authorList;
public Book(String title, List<String> authorList) {
this.title = title;
this.authorList = new ArrayList<>(authorList); // 防禦性拷貝
}
// 省略 getter 方法
}
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/185797.html