สร้างวัตถุจากวัตถุที่มีอยู่โดยใช้ลอมบอก


100

สมมติว่าฉันมีคลาสที่มีคำอธิบายประกอบลอมบอกเช่น

@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");

ฉันไม่พบสิ่งนี้ในเอกสารของลอมบอก

คำตอบ:


223

คุณสามารถใช้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 (); จะสร้างตัวสร้างใหม่ที่เริ่มต้นด้วยค่าทั้งหมดของอินสแตนซ์นี้

คำเตือน: ฉันเป็นผู้พัฒนาลอมบอก


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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.