使用@Builder(toBuilder = true)而不是setter是一种开销吗?

问题描述 投票:1回答:1

我总是努力使我的代码完全不可变,而根本不使用setter。

当我需要更新对象,dto或实体时,我使用@Builder(toBuilder = true)而不是setter。

public Car updateCar(final String id) {
    final Car existing = carRepository.getById(id);
    final Car.CarBuilder builder = existing.toBuilder().make("Mercedes-Benz");
    if (anyCondition) {
        builder.status("READY");
    }
    final Car updatedCar = builder.build();
    return carRepository.save(updatedCar);
}

我想问一下,从性能角度来看,不是将值设置为已经实例化的对象,而是创建一个新对象,这真的很糟糕吗?

也许在上面的代码中,它并不重要,但我也可能需要更改集合中所有对象中的一个字段,因此空间复杂度将是线性的。

你更喜欢什么方法:setters或toBuilder?

P.S。:上面的代码片段只是为了更好地理解我如何利用toBuilder

java performance immutability setter builder
1个回答
2
投票

我想问一下,从性能角度来看,不是将值设置为已经实例化的对象,而是创建一个新对象,这真的很糟糕吗?

你问我们和你自己这个错误的问题。 你不应该真正关心这种简单的数据载体类的性能。 基准(见JMH)并看到。

但从纯粹的理论角度来看,唯一的开销是创建另一个对象(内存中的大小取决于其成员的布局),将原始值/引用从构建器实例传递到结果实例的附加步骤(也许也是更多的GC工作?我甚至不会考虑这一点)。 因此有一些CPU周期。

另请参阅qazxsw poi,看看有多少人和公司正在使用它,并问自己,对于您的简单用例,您是否应该考虑提出这个问题。


上这堂课吧

Immutables

大小约为public class Car { private String maker; private int year; private int kms; // Getter - setters } 字节。 现在,使用诸如的构建器

16 + 4 + 4 + 4 = 28

大小仍然约为public class CarBuilder { private String maker; private int year; private int kms; public CarBuilder setMaker(final String maker) { this.maker = maker; return this; } public CarBuilder setYear(final int year) { this.year = year; return this; } public CarBuilder setKms(final int kms) { this.kms = kms; return this; } public Car createCar() { return new Car(maker, year, kms); } } 字节。

这意味着您将使用构建器至少将堆中使用的字节加倍。 但是,您需要考虑的是Java是基于参考的。这意味着所有创建的对象的指针将被简单地复制到生成的16 + 4 + 4 + 4 = 28实例。对象在内存中仍然是唯一的。


在您编辑之后,您可能要做的是对象池? 在这种情况下,请考虑Car

© www.soinside.com 2019 - 2024. All rights reserved.