当前位置: 首页 > news >正文

不可变类字段修复建议

在设计类时,将字段设为不可变(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)简化实现。

http://www.lryc.cn/news/605010.html

相关文章:

  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘dash’问题
  • Python 程序设计讲义(43):组合数据类型——元组类型:元组的常用操作
  • WSL2搭建基于Docker的ESP32开发环境
  • 机器学习项目完整流程详解
  • 基于C-MTEB/CMedQAv2-rerankingv的Qwen3-1.7b模型微调-demo
  • Android基础(二)了解Android项目
  • 端侧大模型迎来“轻”革命!移远通信 × RWKV 打造“轻量AI大脑”
  • 单片机电路基础
  • 【NCS随笔】如何在hello_world添加蓝牙功能(一)
  • sqli-labs:Less-7关卡详细解析
  • 国内数据集成厂商有哪些?如何选择最适合的数据集成平台?
  • Qt 与物联网(IoT)开发
  • 【Linux】重生之从零开始学习运维之备份恢复
  • String模拟实现的补充说明
  • 第1课:向量与矩阵运算
  • QT中QTableView+Model+Delegate实现一个demo
  • 【ESP32设备通信】-LAN8720与ESP32集成
  • 如何设计一个站内消息系统:架构设计合集(八)
  • 订单识别技术原理及场景应用
  • 【音视频】WebRTC 开发环境搭建-Web端
  • MYSQL:视图
  • Qt 下载说明
  • uniApp实战六:Echart图表集成
  • 实现implements InitializingBean, DisposableBean 有什么用
  • 【MATLAB/Simulink】查看MATLAB以往版本的帮助文档
  • 牛顿-拉夫森法求解非线性方程组
  • 无人机惯性导航模块运行与技术难点!
  • 25年新算法!基于猛禽的优化算法(BPBO):一种元启发式优化算法,附完整免费MATLAB代码
  • 《数学模型》——最大流与最小费用流问题
  • Mediapipe 的某些模型,网络下载不来可以去gitee找找看