如何在Java中创建不可变类?
Java中的不可变类意味着一旦创建了一个对象,我们就不能改变它的内容。在Java中,所有包装类(如 Integer、Boolean、Byte、Short)和 String 类都是不可变的。我们也可以创建自己的不可变类。在继续之前,请先了解不变性的特征,以便在实现相同的同时有一个很好的理解。以下是要求:
- 该类必须声明为 final,这样才能创建子类。
- 类中的数据成员必须声明为私有,这样就不允许直接访问。
- 类中的数据成员必须声明为 final,这样我们就不能在创建对象后更改它的值。
- 参数化构造函数应该初始化执行深度复制的所有字段,以便不能使用对象引用修改数据成员。
- 应在 getter 方法中执行对象的深度复制以返回副本而不是返回实际的对象引用)
Note: There should be no setters or in simpler terms, there should be no option to change the value of the instance variable.
例子
Java
// Java Program to Create An Immutable Class
// Importing required classes
import java.util.HashMap;
import java.util.Map;
// Class 1
// An immutable class
final class Student {
// Member attributes of final class
private final String name;
private final int regNo;
private final Map metadata;
// Constructor of immutable class
// Parameterized constructor
public Student(String name, int regNo,
Map metadata)
{
// This keyword refers to current instance itself
this.name = name;
this.regNo = regNo;
// Creating Map object with reference to HashMap
// Declaring object of string type
Map tempMap = new HashMap<>();
// Iterating using for-each loop
for (Map.Entry entry :
metadata.entrySet()) {
tempMap.put(entry.getKey(), entry.getValue());
}
this.metadata = tempMap;
}
// Method 1
public String getName() { return name; }
// Method 2
public int getRegNo() { return regNo; }
// Note that there should not be any setters
// Method 3
// User -defined type
// To get meta data
public Map getMetadata()
{
// Creating Map with HashMap reference
Map tempMap = new HashMap<>();
for (Map.Entry entry :
this.metadata.entrySet()) {
tempMap.put(entry.getKey(), entry.getValue());
}
return tempMap;
}
}
// Class 2
// Main class
class GFG {
// Main driver method
public static void main(String[] args)
{
// Creating Map object with reference to HashMap
Map map = new HashMap<>();
// Adding elements to Map object
// using put() method
map.put("1", "first");
map.put("2", "second");
Student s = new Student("ABC", 101, map);
// Calling the above methods 1,2,3 of class1
// inside main() method in class2 and
// executing the print statement over them
System.out.println(s.getName());
System.out.println(s.getRegNo());
System.out.println(s.getMetadata());
// Uncommenting below line causes error
// s.regNo = 102;
map.put("3", "third");
// Remains unchanged due to deep copy in constructor
System.out.println(s.getMetadata());
s.getMetadata().put("4", "fourth");
// Remains unchanged due to deep copy in getter
System.out.println(s.getMetadata());
}
}
输出
ABC
101
{1=first, 2=second}
{1=first, 2=second}
{1=first, 2=second}