不可变类字段修复建议

在设计类时,将字段设为不可变(immutable)可提升代码的健壮性和线程安全性。以下是修复可变字段为不可变的建议和步骤:


核心原则

  1. 无 Setter 方法:禁止提供修改字段的方法。

  2. 字段用 final 修饰:强制在构造时初始化。

  3. 防御性拷贝:对引用类型字段,构造/返回时进行深拷贝。

  4. 类本身不可变:避免子类破坏不可变性(如将类声明为 final)。


修复步骤与示例

1. 基础类型字段

直接添加 final,移除 setter 方法:

java

// 修复前(可变)
public class User {
    private int age; // 可变字段
    public void setAge(int age) { this.age = age; }
}

// 修复后(不可变)
public final class User {
    private final int age; // final 字段
    public User(int age) { this.age = age; } // 构造时初始化
    public int getAge() { return age; } // 无 setter
}
2. 引用类型字段(如数组、集合)
  • 构造时深拷贝

  • Getter 返回不可修改视图/拷贝

java

// 修复前(可变)
public class Data {
    private List<String> items; // 可变集合
    public void setItems(List<String> items) { this.items = items; }
}

// 修复后(不可变)
public final class Data {
    private final List<String> items;

    public Data(List<String> items) {
        this.items = new ArrayList<>(items); // 深拷贝传入集合
    }

    public List<String> getItems() {
        return Collections.unmodifiableList(items); // 返回只读视图
        // 或返回深拷贝:return new ArrayList<>(items);
    }
}
3. 自定义对象字段

确保引用的对象本身不可变:

java

public final class Address { // 被引用的类也需不可变
    private final String city;
    public Address(String city) { this.city = city; }
    public String getCity() { return city; }
}

public final class User {
    private final Address address; // 引用不可变对象
    public User(Address address) {
        this.address = new Address(address.getCity()); // 深拷贝
    }
    public Address getAddress() {
        return new Address(address.getCity()); // 返回拷贝
    }
}
4. 避免外部修改(防御性编程)
  • 如果字段是数组:

    java

    public final class ImmutableArray {
        private final int[] array;
    
        public ImmutableArray(int[] array) {
            this.array = Arrays.copyOf(array, array.length); // 深拷贝
        }
    
        public int[] getArray() {
            return Arrays.copyOf(array, array.length); // 返回拷贝
        }
    }

关键检查点

  1. ✅ 所有字段用 final 声明。

  2. ✅ 无 setter 方法

  3. ✅ 引用类型在构造时深拷贝外部数据。

  4. ✅ Getter 返回只读视图或深拷贝

  5. ✅ 类本身为 final(防止子类覆盖方法破坏不可变性)。


不可变类的优势

  • 线程安全:无需同步,天然线程安全。

  • 易于维护:状态在构造后永不改变。

  • 安全共享:可自由缓存、重用对象(如 String)。


注意事项

  • 深拷贝可能影响性能,需权衡场景。

  • 对复杂嵌套对象,确保整个引用链不可变。

  • 使用不可变集合库(如 Guava ImmutableList)简化实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zqmattack

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值