Побудуйте об’єкт із існуючого за допомогою lombok


102

Скажімо, у мене є клас, котрий коментує ломбок

@Builder
class Band {
   String name;
   String type;
}

Я знаю, що можу:

Band rollingStones = Band.builder().name("Rolling Stones").type("Rock Band").build();

Чи існує простий спосіб створити об’єкт Foo, використовуючи існуючий об’єкт як шаблон і змінивши одне з його властивостей?

Щось на зразок:

Band nirvana = Band.builder(rollingStones).name("Nirvana");

Я не можу знайти це в документації lombok.

Відповіді:


225

Ви можете використовувати toBuilderпараметр, щоб надати вашим примірникам toBuilder()метод.

@Builder(toBuilder=true)
class Foo {
   int x;
   ...
}

Foo f0 = Foo.builder().build();
Foo f1 = f0.toBuilder().x(42).build();

З документації :

Якщо ви використовуєте @Builder для генерації конструкторів для створення екземплярів вашого власного класу (це завжди так, якщо не додавати @Builder до методу, який не повертає ваш власний тип), ви можете використовувати @Builder (toBuilder = true), щоб також генерувати метод екземпляра у вашому класі, який називається toBuilder (); він створює новий конструктор, який починається з усіх значень цього екземпляра.

Застереження: я розробник lombok.


11
@Mustafa Там також @Wither, що є більш ефективним для зміни окремих полів: Foo f1 = f0.withX(42).
maaartinus

@maaartinus Я думаю, @Witherгенерує за допомогою * методів, які завжди повертають новий об'єкт, замість того, щоб встановлювати поле існуючого об'єкта. Це низька ефективність.
MGhostSoft

2
@MGhostSoft Я, очевидно, припускаю, що створення нового об'єкта - це мета. Таким чином, ми досить поширені, оскільки незмінні об'єкти використовуються дедалі більше. ++ × @WitherНайкраще підходить для зміни одного поля . Фот більше двох, toBuilderвиграє. Дивіться мою відповідь нижче.
maaartinus

2
А для нульових полів (тобто копія об’єкта без будь-яких змін) @Witherвзагалі не працюватиме, але працює .toBuilder().build().
M. Justin

38

Чи існує простий спосіб створити об’єкт Foo, використовуючи існуючий об’єкт як шаблон і змінивши одне з його властивостей? ( наголос мій )

Якщо ви дійсно хочете змінити одну властивість, тоді є більш приємний та ефективний спосіб:

@With
class Band {
   String name;
   String type;
}

Band nirvana = rollingStones.withName("Nirvana");

Холка не створює сміття, але може змінити лише одне поле. Для зміни багатьох полів ви можете використовувати

withA(a).withB(b).withC(c)....

і виробляють тонни сміття (усі проміжні результати), але чим toBuilderефективніше та природніше.

ПРИМІТКА. У старих версіях ломбоку використовували @Witherанотації. Див. Початок документації .


1
чи справді це створило б стільки сміття? Я думаю, що це все неглибокі копії, за винятком поля, яке ви замінюєте (покладаючись на уявлення, що ви зробите об'єкт незмінним, якщо це саме те, що призначено). "Сміття" в основному буде відкинутими посиланнями на об'єкт верхнього рівня (хоча, я думаю, багато примітивів може призвести до збільшення кількості сміття).
jm0

1
@ jm0 Звичайно, це все неглибокі копії. Під "тоннами сміття" я мав на увазі n-1об'єкти для ряду nдзвінків withSomething. Об'єкт коштує приблизно кілька байтів плюс 4 або 8 байт на посилання плюс 1 до 8 байт на примітив. Отже, ми говоримо про десятки байтів за дзвінок. Зазвичай нічого страшного.
maaartinus
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.