如何在Java中创建不可变类
如何在Java中创建不可变类?
不可变类
不可变类是指那些一旦创建对象后,其值就不会改变的类。Java中的所有包装类都是不可变类。例如:String、BigInteger、Byte等。
不可变类非常适合缓存,因为您不必担心值的变化。
不可变类的另一个好处是它天生就是线程安全的。
如何在Java中创建不可变类?
要在Java中创建不可变类,我们需要确保通过任何机制创建的类都不能提供改变其对象值的方法。为了实现这一点,我们可以遵循几个规则,这些规则有助于防止这种行为。
将类声明为 final,这样它就不能被继承。如果类不能被继承,子类就无法进行任何更改。
所有类成员都应该是私有的,这样它们就不能在类外部被访问。
类不应该包含任何 setter 方法来改变类成员的值。
getter 方法应该返回类成员的副本。
变量只能通过构造函数进行初始化。
在getter方法中执行克隆或深拷贝,返回副本而不是返回实际的对象引用。
示例1:
- import java.util.HashMap;
- import java.util.Map;
- // 类被声明为final
- final class Immutable {
- // 私有类成员
- private final String name;
- private final int date;
- private final Map<String, String> metadata;
- public Immutable(String name, int date, Map<String, String> metadata) {
- // 类成员通过构造函数初始化
- this.name = name;
- this.date = date;
- Map<String, String> tempMap = new HashMap<>();
- for (Map.Entry<String, String> entry : metadata.entrySet()) {
- tempMap.put(entry.getKey(), entry.getValue());
- }
- this.metadata = tempMap;
- }
- // getter方法返回类成员的副本
- public String getName() {
- return name;
- }
- public int getDate() {
- return date;
- }
- public Map<String, String> getMetadata() {
- // 创建带有HashMap引用的Map
- Map<String, String> tempMap = new HashMap<>();
- for (Map.Entry<String, String> entry :
- this.metadata.entrySet()) {
- tempMap.put(entry.getKey(), entry.getValue());
- }
- return tempMap;
- }
- }
示例2:
- final class Immutable {
- private final Mutable mutableClass;
- public Immutable(Mutable mutableClass) {
- super();
- this.mutableClass = mutableClass;
- }
- public Mutable getMutableClass() throws CloneNotSupportedException {
- return (Mutable) mutableClass.clone();
- }
- }
- class Mutable implements Cloneable {
- public String variable;
- public Mutable(String variable) {
- super();
- this.variable = variable;
- }
- public String getVariable() {
- return variable;
- }
- public void setVariable(String variable) {
- this.variable = variable;
- }
- public Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
- @Override
- public String toString() {
- return "Mutable{" +
- "variable='" + variable + '\'' +
- '}';
- }
- }
- public class MainClass {
- public static void main(String[] args) throws Exception {
- Immutable immutable = new Immutable(new Mutable("Some String"));
- Mutable mutable = immutable.getMutableClass();
- System.out.println(mutable);
- mutable.setVariable("Updated String");
- System.out.println(immutable.getMutableClass());
- }
- }
关键要点
final关键字:确保类不能被继承
私有成员:防止外部直接访问
无setter方法:防止值被修改
深拷贝:在getter方法中返回对象副本
构造函数初始化:所有值只能通过构造函数设置
不可变类的优势
线程安全:天生支持多线程环境
缓存友好:值不会改变,适合缓存
简化代码:减少了状态管理的复杂性
防御性编程:防止意外的值修改
注意事项
对于包含可变对象的不可变类,必须进行深拷贝
性能考虑:深拷贝可能带来性能开销
内存使用:不可变对象可能创建更多对象实例
