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

不可变类字段修复建议

在设计类时,将字段设为不可变(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.xdnf.cn/news/16660.html

相关文章:

  • UE5多人MOBA+GAS 番外篇:将冷却缩减属性应用到技能冷却中
  • 常见CMS
  • MCP提示词工程:上下文注入的艺术与科学
  • Visual Studio Code 使用指南 (2025年版)
  • 从硬编码到自主智能体:营销AI的20年技术演进与未来展望
  • LeetCode 283 - 移动零
  • Python 程序设计讲义(27):字符串的用法——字符串的常用操作
  • 三步给小智ESP32S3智能语音硬件接入小程序打通MCP服务
  • 【Linux】pthread学习笔记
  • 专业Python爬虫实战教程:逆向加密接口与验证码突破完整案例
  • ubuntu18.04制作raid0
  • 51c大模型~合集161
  • 代码随想录算法训练营第三十五天
  • 车载刷写架构 --- 整车刷写中为何增加了ECU 队列刷写策略?
  • idea运行tomcat日志乱码问题
  • PostgreSQL锁机制详解:从并发控制到死锁检测
  • STM32——HAL库
  • LangChain和LangGraph 里面的 `create_react_agent`有什么不同
  • 基于SpringBoot和Leaflet集成在线天气服务的区县当前天气WebGIS实战
  • VUE -- 基础知识讲解(一)
  • RabbitMQ工作模式
  • 【C#|C++】C#调用C++导出的dll之非托管的方式
  • C# _泛型
  • python线性回归:从原理到实战应用
  • 在 Vue 中,如何在回调函数中正确使用 this?
  • 单片机学习笔记.PWM
  • linux——ps命令
  • 【tips】小程序css ➕号样式
  • 站点到站点-主模式
  • cartographer 点云数据的预处理