网站首页 > 技术文章 正文
不可变类是指那些一旦创建对象后,其值就不会改变的类。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方法中返回对象副本
- 构造函数初始化:所有值只能通过构造函数设置
不可变类的优势
- 线程安全:天生支持多线程环境
- 缓存友好:值不会改变,适合缓存
- 简化代码:减少了状态管理的复杂性
- 防御性编程:防止意外的值修改
注意事项
- 对于包含可变对象的不可变类,必须进行深拷贝
- 性能考虑:深拷贝可能带来性能开销
- 内存使用:不可变对象可能创建更多对象实例
猜你喜欢
- 2025-07-20 Hutool JSONUtil巧妙过滤null值:JSON转Map数据清洗的终极方案
- 2025-07-20 HBase基础知识,面向列的实时分布式数据库
- 2025-07-20 Java Map 所有的值转为String类型
- 2025-07-20 HashMap-entrySet( )原理(hashmap原理详解)
- 2025-07-20 常见的Java性能问题,我来手把手教你定位!
- 2025-07-20 面试怕被问Hashmap,多看看这个文章
- 2025-07-20 Map遍历的四种方法效率对比(map遍历方式)
- 2025-07-20 面试官:知道ThreadLocal嘛?谈谈你对它的理解?
- 2025-07-20 内存溢出OutOfMemoryError科普系列一
- 2025-07-20 HashMap详解(hashmap理解)
- 最近发表
-
- Qt编程进阶(63):Qt Quick高级控件的使用
- Qt编程进阶(47):QML鼠标事件处理(qt编程难不难)
- 使用Xamarin和Visual Studio开发Android可穿戴设备应用
- Qt使用教程:创建Qt Quick应用程序(三)
- QML性能优化 | 常见界面元素优化(qml布局自适应大小)
- Qt使用教程:创建移动应用程序(二)
- Qt Quick 多媒体开发播放音乐和视频
- Qt使用教程:创建Qt Quick UI表单(三)
- 如何将 Qt 3D 渲染与 Qt Quick 2D 元素结合创建太阳系行星元素?
- QML控件:TextInput, TextField, TextEdit, TextArea用法及自定义
- 标签列表
-
- axure 注册码 (25)
- exploit db (21)
- mutex_lock (30)
- oracleclient (27)
- nfs (25)
- springbatch (28)
- oracle数据库备份 (25)
- dir (26)
- connectionstring属性尚未初始化 (23)
- output (32)
- panel滚动条 (28)
- centos 5 4 (23)
- sql学习 (33)
- c 数组 (33)
- pascal语言教程 (23)
- ppt 教程 (35)
- java7 (24)
- 自适应网站制作 (32)
- server服务自动停止 (25)
- 超链接去掉下划线 (34)
- 什么是堆栈 (22)
- map entry (25)
- ubuntu装qq (25)
- outputstreamwriter (26)
- fill_parent (22)