[英]Make immutable Java object
我的目標是使 Java 對象不可變。 我有一個班級Student
。 我以以下方式對其進行編碼以實現不變性:
public final class Student {
private String name;
private String age;
public Student(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
}
我的問題是,實現Student
類不變性的最佳方法是什么?
嚴格來說,您的類不是一成不變的,它只是有效地不可變。 要使其不可變,您需要使用final
:
private final String name;
private final String age;
盡管差異可能看起來很微妙, 但它可以在多線程上下文中產生顯着差異。 不可變類本質上是線程安全的,有效的不可變類只有在安全發布時才是線程安全的。
要創建一個不可變的類,您必須考慮以下幾點:
final
- 你已經有了private
和final
字段 - 在代碼中進行適當更改List
或Date
,將它們設為final
不夠的。 你應該從他們的getters
返回一個防御性副本,這樣他們的狀態就不會因為調用方法而改變。 對於第 4 點,假設您的類中有一個Date
字段,那么該字段的 getter 應如下所示:
public Date getDate() {
return new Date(this.date.getTime());
}
當您的可變字段本身包含一些可變字段,而該可變字段又可以包含其他一些可變字段時,制作防御性副本可能會令人頭疼。 在這種情況下,您需要迭代地復制它們中的每一個。 我們將這個可變字段的迭代副本命名為Deep Copy 。
自己實現深拷貝可能很麻煩。 但是,把這個問題分開,你應該再次考慮你的類設計,一旦你發現自己陷入了制作深度防御性副本的要求。
如何使可變對象不可變?
我們為什么要創建不可變對象?
不可變對象只是其狀態(對象的數據)在構造后無法更改的對象。
使用final
關鍵字:
private final String name;
private final String age;
將變量設為私有且沒有 setter 方法將適用於原始數據類型。 如果我的班級有任何對象集合?
使用集合對象使任何類不可變?
使用 extends 集合類編寫自己的集合對象,並遵循私有變量而不是 setter 方法。 或返回您的集合對象的克隆對象。
public final class Student {
private StudentList names;//Which is extended from arraylist
public Student() {
names = DAO.getNamesList()//Which will return All Student names from Database its upto you how you want to implement.
}
public StudentList getStudentList(){
return names;//you need to implement your own methods in StudentList class to iterate your arraylist; or you can return Enumeration object.
}
public Enumeration getStudentNamesIterator(
Enumeration e = Collections.enumeration(names);
return e;
}
public class StudentList extends ArrayList {
}
這很好,但我也會將這些字段設為final
。
此外,我會將年齡int
或double
而不是 String。
稍微擴展一下答案。
final
與Immutable
但如果您以某種方式使用它,您可以使用final
使某些事物不可變。
某些類型是不可變的,因為它們表示不變的值而不是狀態可變的對象。 字符串、數字等是不可變的。 最后,通常我們的對象歸結為最終引用不可變值的數據結構,但我們通過將新值分配給相同的字段名稱來更改數據結構。
因此,要使某些東西真正不可變,您需要確保一直使用 final,直到到達每個字段,並達到組合樹底部的每個值。 否則,某些東西可能會從您的對象下方發生變化,並且它並不是完全不可變的。
您的示例已經是不可變對象,因為 Student 類中的字段只能在實例初始化時設置。
要使對象不可變,您必須執行以下步驟:
現在回答為時已晚,但可能會幫助其他有此問題的人。
我認為這個鏈接幫助更多閱讀更多: http : //javarevisited.blogspot.com/2013/03/how-to-create-immutable-class-object-java-example-tutorial.html#ixzz40VDQDDL1
它已經是不可變的——一旦你初始化它,你就不能改變它的內容,因為你還沒有創建 setter。 您可以將 final 關鍵字添加到變量中。
將所有變量設置為final
並在設置某個字段時,使其返回對具有新設置值的新Student
對象的引用,如String
。
您只需遵循本示例中顯示的指南(谷歌中的第一個結果): http : //www.javapractices.com/topic/TopicAction.do? Id= 29
這里有一些規則,這有助於在 Java 中使類不可變: 1. 不可變對象的狀態在構造后不能修改,任何修改都應產生新的不可變對象。 2. Immutable 類的所有字段都應該是最終的。 3. 對象必須正確構造,即對象引用在構造過程中不能泄漏。 4.對象應該是最終的,以限制子類改變父類的不變性。
例子:
public final class Contacts {
private final String name;
private final String mobile;
public Contacts(String name, String mobile) {
this.name = name;
this.mobile = mobile;
}
public String getName(){
return name;
}
public String getMobile(){
return mobile;
}
}
請參閱此鏈接: http : //javarevisited.blogspot.in/2013/03/how-to-create-immutable-class-object-java-example-tutorial.html
不要提供“ setter
”方法——修改字段或字段引用的對象的方法。
將所有字段設為final
和private
。
不允許子類覆蓋方法。 最簡單的方法是將類聲明為final
。
a. 更復雜的方法是使constructor
私有並在工廠方法中構造實例。
如果實例字段包含對可變對象的引用,則不允許更改這些對象:
a. 不要提供修改可變對象的方法。
灣不要共享對可變對象的引用。 永遠不要存儲對傳遞給構造函數的外部可變對象的引用; 如有必要,創建副本並存儲對副本的引用。 同樣,必要時創建內部可變對象的副本,以避免在方法中返回原始對象。
您可以使用JEP 395:記錄功能(作為 Java SE 16 的一部分引入)以簡潔的方式創建不可變類。
如果你已經通過上面的鏈接,你一定已經想出你可以簡單地做到這一點
record Student(String name, String age) { }
你依次得到的是:
final class Student
。Student(String name, String age)
相同的規范構造函數。private final
字段、 name
和age
以及它們對應的具有相同名稱和返回類型的public
訪問器方法。equals
、 hashCode
和toString
方法。學生.java
record Student(String name, String age) { }
主程序
class Main{
public static void main(String[] args) {
Student s1 = new Student("Bharat", "10 Years");
Student s2 = new Student("Arvind", "10 Years");
System.out.println(s1);
System.out.println(s1.equals(s2));
System.out.println(s1.age().equals(s2.age()));
}
}
輸出:
Student[name=Bharat, age=10 Years]
false
true
將類或變量設為 final 就足夠了
Public final class constants
{
private final String name;
private final String mobile;
// code
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.