温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java不可变怎么实现的

发布时间:2026-07-16 10:16:49 来源:亿速云 阅读:84 作者:小樊 栏目:编程语言

在 Java 中,“不可变(Immutable)”通常指对象一旦创建,其状态(字段值)就不能被修改。常见的不可变类有 StringInteger、以及 Java 新引入的 Record

下面系统地讲一下 Java 不可变对象的实现方式、原理和注意事项


一、不可变对象的核心特征

一个不可变对象通常满足以下几点:

  1. 类本身不能被继承(防止子类破坏不可变性)
  2. 所有字段都是 private final(只能赋值一次)
  3. 不提供 setter 方法
  4. 构造方法完成所有初始化
  5. 如果字段是可变对象,要防止外部修改(防御性拷贝)
  6. 类本身是线程安全的(无需额外同步)

二、最典型的不可变类示例

1️⃣ 标准写法(推荐)

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

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

✅ 特点:

  • final class:不能被继承
  • final 字段:只能赋值一次
  • 没有 setter
  • 基本类型 + String(天然不可变)

三、包含可变对象时如何保证不可变(重点)

❌ 错误示例(有风险)

class Address {
    public String city;
}

final class User {
    private final Address address;

    public User(Address address) {
        this.address = address; // 直接引用外部对象
    }

    public Address getAddress() {
        return address;
    }
}

⚠️ 问题:

  • Address 是可变的
  • 外部修改 address.cityUser 就变了

✅ 正确做法:防御性拷贝

class Address {
    private String city;

    public Address(Address other) {
        this.city = other.city;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
}

final class User {
    private final Address address;

    public User(Address address) {
        this.address = new Address(address); // 拷贝
    }

    public Address getAddress() {
        return new Address(address); // 返回拷贝
    }
}

✅ 关键点:

  • 构造时拷贝
  • 返回时拷贝
  • 不暴露内部可变对象

四、String 为什么是不可变的?

public final class String {
    private final char value[];
}

原因:

  • final class
  • private final char[]
  • 不提供修改数组的方法
  • 任何“修改”都会返回新对象

五、Java 14+ Record(最简洁的不可变类)

public record User(String name, int age) {}

✅ 自动具备:

  • final
  • final 字段
  • 无 setter
  • 构造器
  • equals / hashCode / toString

⚠️ 注意:

  • 如果字段是可变对象,仍然需要防御性拷贝

六、不可变对象的优缺点

✅ 优点

优点 说明
线程安全 无需加锁
可缓存 如 String 常量池
易推理 状态不会变化
适合 HashMap / HashSet hashCode 稳定

❌ 缺点

  • 频繁创建对象(内存 + GC)
  • 修改需要创建新对象

七、常见面试总结一句话

Java 不可变对象通过 final 类、final 字段、无 setter、构造器初始化,并对可变对象进行防御性拷贝来实现。

如果你愿意,我可以:

  • 对比 String vs StringBuffer
  • JDK 源码 讲不可变
  • 结合 并发 / 设计模式 讲不可变的意义
向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI