Zbuduj obiekt z istniejącego za pomocą lombok


105

Powiedzmy, że mam klasę z adnotacjami typu lombok

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

Wiem, że potrafię:

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

Czy istnieje łatwy sposób na utworzenie obiektu Foo, używając istniejącego obiektu jako szablonu i zmieniając jedną z jego właściwości?

Coś jak:

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

Nie mogę znaleźć tego w dokumentacji lomboka.

Odpowiedzi:


232

Możesz użyć tego toBuilderparametru, aby nadać instancji toBuilder()metodę.

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

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

Z dokumentacji :

Jeśli używasz @Builder do generowania konstruktorów do tworzenia instancji własnej klasy (tak jest zawsze, chyba że dodasz @Builder do metody, która nie zwraca własnego typu), możesz użyć @Builder (toBuilder = true), aby również wygenerować metoda instancji w Twojej klasie o nazwie toBuilder (); tworzy nowy konstruktor, który zaczyna się od wszystkich wartości tej instancji.

Zastrzeżenie: jestem programistą lombok.


12
@Mustafa Jest też @Wither, co jest bardziej efektywne dla pojedynczych zmian pola: Foo f1 = f0.withX(42).
maaartinus

Myślę, że @maaartinus @Withergeneruje z metodami *, które zawsze zwracają nowy obiekt, zamiast ustawiać pole istniejącego obiektu. To ma niską wydajność.
MGhostSoft

3
@MGhostSoft Zakładam oczywiście, że naszym celem jest stworzenie nowego obiektu. Tak więc jesteśmy dość powszechni, ponieważ niezmienne obiekty są coraz częściej używane. ++ × Do zmiany pojedynczego pola @Withernajlepiej. Fot więcej niż dwa, toBuilderwygrywa. Zobacz moją odpowiedź poniżej.
maaartinus

2
A dla zerowych pól (tj. Kopii obiektu bez żadnych zmian), @Withernie będzie działać, ale .toBuilder().build()będzie.
M. Justin

40

Czy istnieje łatwy sposób na utworzenie obiektu Foo, używając istniejącego obiektu jako szablonu i zmieniając jedną z jego właściwości? ( podkreślenie moje )

Jeśli naprawdę chcesz zmienić jedną właściwość, jest lepszy i wydajniejszy sposób:

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

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

Uschnięcie nie tworzy śmieci, ale może zmienić tylko jedno pole. Aby zmienić wiele pól, możesz użyć

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

i produkuje tony śmieci (wszystkie pośrednie wyniki), ale niż toBuilderjest bardziej wydajne i bardziej naturalne.

UWAGA: Starsze wersje lombok używały @Witheradnotacji. Zobacz początek dokumentacji .


1
czy naprawdę stworzyłoby tyle śmieci? Myślę, że to wszystko jest płytkie kopie, z wyjątkiem pola, które zastępujesz (polegając na założeniu, że już sprawisz, że obiekt będzie niezmienny, jeśli jest to zamierzone). „Śmieci” będą głównie odwołaniami do odrzuconych obiektów najwyższego poziomu (chociaż myślę, że wiele prymitywów może również skutkować większą ilością śmieci).
jm0

1
@ jm0 Jasne, to wszystko jest płytkie. Mówiąc „tony śmieci”, miałem na myśli n-1obiekty do serii nwywołań withSomething. Obiekt kosztuje około kilku bajtów plus 4 lub 8 bajtów na odniesienie plus 1 do 8 bajtów na prymityw. Więc mówimy o dziesiątkach bajtów na wywołanie. Zwykle nic wielkiego.
maaartinus
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.