温馨提示×

温馨提示×

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

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

如何创建不可变Java对象

发布时间:2026-07-16 09:50:56 来源:亿速云 阅读:86 作者:小樊 栏目:编程语言

在 Java 中,**不可变对象(Immutable Object)**是指对象一旦创建,其状态(字段值)就不能再被修改。创建不可变对象是编写健壮、线程安全代码的重要手段。

下面是创建不可变 Java 对象的完整方法和示例


一、创建不可变对象的核心原则

要让一个对象不可变,通常需要遵守以下 5 条规则:

✅ 1. 类本身不能被继承

防止子类修改行为
→ 使用 final 修饰类

public final class Person {
}

✅ 2. 所有字段都是 privatefinal

  • private:防止外部直接访问
  • final:保证对象创建后不可被重新赋值
private final String name;
private final int age;

✅ 3. 不提供 setter 方法

只允许通过构造方法初始化状态。


✅ 4. 通过构造方法初始化所有字段

构造对象时必须提供完整状态。


✅ 5. 如果字段是可变对象,必须防御性拷贝

这是最容易出错的地方


二、最简单的不可变对象示例

public final class Person {

    private final String name;
    private final int age;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

✅ 原因:

  • String 本身是不可变的
  • 基本类型 int 天然不可变

三、包含可变对象的不可变对象(重点)

❌ 错误示例(会破坏不可变性)

public final class Student {
    private final Date birthDate;

    public Student(Date birthDate) {
        this.birthDate = birthDate;
    }

    public Date getBirthDate() {
        return birthDate; // 外部可修改
    }
}

外部可以这样破坏:

Date date = new Date();
Student s = new Student(date);
date.setTime(0); // 修改了 Student 内部状态

✅ 正确写法(防御性拷贝)

import java.util.Date;

public final class Student {

    private final Date birthDate;

    public Student(Date birthDate) {
        this.birthDate = new Date(birthDate.getTime()); // 拷贝
    }

    public Date getBirthDate() {
        return new Date(birthDate.getTime()); // 拷贝
    }
}

✅ 确保:

  • 构造时拷贝
  • 返回时拷贝

四、使用集合时如何保持不可变

❌ 错误示例

private final List<String> list;

public List<String> getList() {
    return list;
}

外部可以:

s.getList().add("hack");

✅ 正确做法 1:返回不可变视图

import java.util.Collections;
import java.util.List;

public final class Group {

    private final List<String> members;

    public Group(List<String> members) {
        this.members = new ArrayList<>(members);
    }

    public List<String> getMembers() {
        return Collections.unmodifiableList(members);
    }
}

✅ 正确做法 2(Java 9+):使用不可变集合

import java.util.List;

public final class Group {

    private final List<String> members;

    public Group(List<String> members) {
        this.members = List.copyOf(members);
    }

    public List<String> getMembers() {
        return members;
    }
}

五、使用 Builder 模式创建复杂不可变对象(推荐)

当字段很多时使用 Builder 更加优雅。

public final class User {

    private final String name;
    private final int age;

    private User(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
    }

    public static class Builder {
        private String name;
        private int age;

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder age(int age) {
            this.age = age;
            return this;
        }

        public User build() {
            return new User(this);
        }
    }
}

使用方式:

User user = new User.Builder()
        .name("Tom")
        .age(20)
        .build();

六、不可变对象的好处

线程安全(无需加锁)
易于缓存
减少副作用
更安全、更易推理


七、常见不可变类示例

  • String
  • IntegerLong 等包装类
  • BigDecimal
  • LocalDateLocalDateTime
  • Collections.unmodifiableXXX

如果你愿意,我可以:

  • 对比 可变 vs 不可变
  • 讲解 为什么 String 是不可变的
  • 结合 并发编程 讲不可变对象的重要性
向AI问一下细节

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

AI