Skip to content

什么是Java中的不可变类?

843字约3分钟

2024-09-12

在Java中,不可变类(Immutable Class)是指一旦创建,其对象的状态(字段值)就无法被修改的类。换句话说,类的所有实例都是只读的,不能在创建后通过修改字段来改变其内容。

不可变类的常见例子是String类,创建的字符串对象一旦初始化,它的值不能被更改。

创建不可变类的要点

为了创建一个不可变类,通常需要遵循以下几个关键点:

  1. 类必须声明为final,以防止子类继承后改变其不可变性。

    public final class ImmutableClass { ... }
  2. 所有字段必须是私有的和最终的private final),确保它们在初始化之后无法被修改。

    private final int value;
  3. 不提供setter方法。因为setter方法会允许修改字段的值,所以不可变类不会提供这些方法。

    // 没有setter方法
  4. 通过构造函数初始化所有字段。对象的所有字段都必须通过构造函数进行初始化,保证在对象创建时所有值都已经确定。

    public ImmutableClass(int value) {
        this.value = value;
    }
  5. 如果类包含可变对象(例如数组、集合、或自定义的类对象)作为字段,必须确保这些对象的引用不会被修改。这可以通过:

    • 在构造函数中创建这些可变对象的防御性拷贝(deep copy)。
    • 在返回可变对象的getter方法中返回其拷贝,而不是原始对象。

    示例:

    public final class ImmutableClass {
        private final int[] array;
    
        public ImmutableClass(int[] array) {
            // 防御性拷贝,防止外部对象对传入数组的修改影响类内部
            this.array = array.clone();
        }
    
        public int[] getArray() {
            // 返回数组的副本,而不是直接返回内部的数组引用
            return array.clone();
        }
    }

不可变类的优点

  1. 线程安全:不可变类的对象是天然线程安全的,因为它们的状态在创建后不能被修改。因此,不需要同步(synchronized)来保证线程安全。

  2. 易于维护:不可变对象的状态不会在对象生命周期中改变,减少了调试和维护时的复杂性。

  3. 可以作为缓存或集合的键:因为不可变对象的哈希值(hashcode)在创建后不会改变,因此它们适合作为HashMap的键或放在HashSet中。

  4. 可以放心共享:因为不可变对象不会变,可以在不同地方、不同线程中自由共享而不会引发竞态条件。

示例:创建不可变类

以下是一个简单的不可变类的示例:

public final class ImmutablePerson {
    private final String name;
    private final int age;

    public ImmutablePerson(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

在这个例子中,ImmutablePerson类是不可变的:

  • 它被声明为final,不能被子类继承。
  • nameage是私有的并且是final,只能在构造时赋值。
  • 没有setter方法,只提供getter方法来访问字段。

总结

不可变类在并发编程、缓存设计、数据传输等场景中有着广泛的应用。通过遵循不可变类的设计原则,可以构建出更加安全、可维护和高效的Java程序。