我一直在努力使我的代码完全不可变,根本不使用setter。
当我需要更新对象,dto或实体时,我使用@Builder(toBuilder = true)
而不是二传手。
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);
}
我想问你,从性能的角度来看,不是创建一个已实例化的对象而不是为它设置值,而是创建一个新对象,这真的很糟糕吗?
也许在上面的代码中,它并不重要,但我还可能需要更改集合中所有对象的一个字段,因此空间复杂度是线性的。
您更喜欢哪种方法:setter或toBuilder?
P.S .:上面的代码段只是为了更好地理解我如何利用toBuilder
答案 0 :(得分:2)
我想问你,表演真的很糟糕吗? 观点,而不是将值设置为已经 实例化的对象,我创建一个新对象?
您是在问我们自己,还是您自己,是错的问题。
对于这种简单的数据载体类,您实际上不必担心性能。
基准测试(请参见JMH)。
但是从纯粹的理论观点来看,唯一的开销是创建另一个对象(内存中的大小取决于其成员的布局),这是传输原始值/引用的附加步骤生成器实例到生成的实例(也许还有更多的GC工作?我什至不考虑)。
因此,需要更多的CPU周期。
还要查看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);
}
}
大小仍然约为16 + 4 + 4 + 4 = 28
字节。
这意味着您至少要使用构建器将 double 个字节用于堆中,以仅用于类。
但是,您需要考虑的是Java是基于引用的。这意味着所有创建的对象的 pointers 都将被简单地复制到产生的Car
实例中。这些对象在内存中仍然是唯一的。
编辑后,也许您想做的是对象池化?
在这种情况下,请考虑Apache Commons Pool。