Bangun sebuah objek dari yang sudah ada menggunakan lombok

102

Katakanlah saya memiliki kelas beranotasi lombok seperti

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

Saya tahu saya bisa melakukan:

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

Apakah ada cara mudah untuk membuat objek Foo menggunakan objek yang ada sebagai templat dan mengubah salah satu propertinya?

Sesuatu seperti:

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

Saya tidak bisa menemukan ini di dokumentasi lombok.

Mustafa
sumber

Jawaban:

225

Anda dapat menggunakan toBuilderparameter untuk memberikan toBuilder()metode pada instance Anda .

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

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

Dari dokumentasi :

Jika menggunakan @Builder untuk menghasilkan pembangun untuk menghasilkan instance kelas Anda sendiri (ini selalu terjadi kecuali menambahkan @Builder ke metode yang tidak mengembalikan tipe Anda sendiri), Anda dapat menggunakan @Builder (toBuilder = true) untuk juga menghasilkan metode instance di kelas Anda yang disebut toBuilder (); itu membuat pembangun baru yang dimulai dengan semua nilai dari instance ini.

Penafian: Saya adalah pengembang lombok.

Roel Spilker
sumber
11
@Mustafa Ada juga @Wither, yang lebih efisien untuk perubahan field: Foo f1 = f0.withX(42).
maaartinus
@maaartinus saya pikir @Withermenghasilkan dengan * metode yang selalu mengembalikan objek baru, bukan pengaturan bidang objek yang ada. Ini efisiensi rendah.
MGhostSoft
2
@MGhostSoft Saya jelas berasumsi bahwa membuat objek baru adalah tujuan. Jadi kami cukup umum karena objek yang tidak berubah semakin banyak digunakan. ++ × Untuk mengubah satu bidang, @Witheryang terbaik. Fot lebih dari dua, toBuildermenang. Lihat jawaban saya di bawah.
maaartinus
2
Dan untuk bidang nol (yaitu salinan objek tanpa perubahan apa pun), @Withertidak akan berfungsi sama sekali tetapi .toBuilder().build()akan berfungsi .
M. Justin
38

Apakah ada cara mudah untuk membuat objek Foo menggunakan objek yang ada sebagai templat dan mengubah salah satu propertinya? ( penekanan saya )

Jika Anda benar-benar ingin mengubah satu properti, ada cara yang lebih baik dan lebih efisien:

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

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

The layu tidak menghasilkan sampah, tetapi dapat mengubah hanya satu bidang. Untuk mengubah banyak bidang, Anda bisa menggunakan

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

dan menghasilkan berton-ton sampah (semua hasil antara) tetapi toBuilderlebih efisien dan lebih alami.

CATATAN: Versi lombok yang lebih lama telah menggunakan @Witheranotasi. Lihat awal dokumentasi .

maaartinus
sumber
1
apakah itu benar-benar akan menghasilkan banyak sampah? Saya pikir itu semua salinan dangkal kecuali bidang yang Anda ganti (mengandalkan gagasan bahwa Anda akan membuat objek sudah tidak berubah jika itu yang diinginkan). "Sampah" sebagian besar akan menjadi referensi objek tingkat atas yang dibuang (meskipun saya rasa banyak primitif dapat menghasilkan lebih banyak sampah juga).
jm0
1
@ jm0 Tentu, itu semua salinan dangkal. Yang saya maksud dengan "ton sampah" adalah n-1objek untuk serangkaian npanggilan withSomething. Sebuah objek berharga seperti beberapa byte ditambah 4 atau 8 byte per referensi ditambah 1 hingga 8 byte per primitif. Jadi kita berbicara tentang puluhan byte per panggilan. Biasanya bukan masalah besar.
maaartinus