You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中类似JavaScript Object.assign的非修改原对象替代方案

当然有啦!Java里要实现这种不可变对象的逐步属性填充,核心思路和JS里的Object.assign完全一致:每次更新属性都返回一个全新的对象,原对象保持纹丝不动。下面给你几种常用的靠谱方案:

Java中实现不可变对象属性更新的方法

1. 手动实现「拷贝+更新」方法(最基础可控)

自己给不可变类写返回新对象的属性更新方法,完全不依赖外部库,逻辑清晰可控。举个Person类的例子:

public final class Person {
    // 所有属性设为final,保证不可变
    private final String name;
    private final Integer age;
    private final String email;

    // 全参构造器(用于创建新对象)
    public Person(String name, Integer age, String email) {
        this.name = name;
        this.age = age;
        this.email = email;
    }

    // 为每个属性提供更新方法,返回全新对象
    public Person withName(String name) {
        return new Person(name, this.age, this.email);
    }

    public Person withAge(Integer age) {
        return new Person(this.name, age, this.email);
    }

    public Person withEmail(String email) {
        return new Person(this.name, this.age, email);
    }

    // 只提供getter,不写setter
    public String getName() { return name; }
    public Integer getAge() { return age; }
    public String getEmail() { return email; }
}

使用起来和JS的Object.assign体验类似:

// 初始全null的对象
Person initialPerson = new Person(null, null, null);
// 逐步填充,每次都生成新对象,原对象不受影响
Person personWithName = initialPerson.withName("Alice");
Person personWithNameAndAge = personWithName.withAge(30);
Person finalPerson = personWithNameAndAge.withEmail("alice@example.com");

2. Builder模式(适合属性较多的场景)

如果你的Person类属性很多,手动写一堆withXxx方法会很繁琐,用Builder模式更优雅——可以基于现有对象生成Builder,修改属性后再构建新对象:

public final class Person {
    private final String name;
    private final Integer age;
    private final String email;

    // 私有构造器,只能通过Builder创建
    private Person(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
        this.email = builder.email;
    }

    // 基于现有对象生成Builder的方法
    public Builder toBuilder() {
        return new Builder()
                .name(this.name)
                .age(this.age)
                .email(this.email);
    }

    // getter方法
    public String getName() { return name; }
    public Integer getAge() { return age; }
    public String getEmail() { return email; }

    // 内部Builder类
    public static class Builder {
        private String name;
        private Integer age;
        private String email;

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

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

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

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

使用示例:

// 初始全null对象
Person initialPerson = new Person.Builder().build();
// 基于原对象修改属性,生成新对象
Person personWithName = initialPerson.toBuilder().name("Bob").build();
Person finalPerson = personWithName.toBuilder().age(25).email("bob@example.com").build();

3. 用Lombok简化样板代码(高效省心)

如果项目里已经在用Lombok,那直接用@Value(生成不可变类)+@With(自动生成withXxx方法),几行代码搞定:

import lombok.Value;
import lombok.With;

@Value // 自动生成final类、final属性、全参构造器、getter等
@With // 自动为所有属性生成返回新对象的withXxx方法
public class Person {
    String name;
    Integer age;
    String email;
}

使用方式和第一种方案完全一样,但代码量直接砍到最少,非常省心。

4. Java 16+ Record类(官方原生不可变方案)

Java 16引入的Record是官方专门为不可变数据类设计的,你可以手动为它添加withXxx方法,或者配合Lombok的@With进一步简化:

// 手动添加with方法的Record
public record Person(String name, Integer age, String email) {
    public Person withName(String name) {
        return new Person(name, this.age, this.email);
    }

    public Person withAge(Integer age) {
        return new Person(this.name, age, this.email);
    }

    public Person withEmail(String email) {
        return new Person(this.name, this.age, email);
    }
}

如果用Lombok的@With,代码会更简洁:

import lombok.With;

@With
public record Person(String name, Integer age, String email) {}

Record本身天生不可变,完美契合你的核心需求。

总结

这些方案的核心都是绝不修改原对象,每次属性更新都返回全新的不可变对象,和JavaScript里Object.assign的设计思路完全匹配。如果不想依赖第三方库,手动写withXxx方法或Builder模式就足够;如果想减少样板代码,Lombok是绝佳选择;Java 16+的Record则是官方推荐的原生方案。

内容的提问来源于stack exchange,提问作者Prashanth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:51:49