[英]Lombok Builder with Immutable lists?
我有以下 class 和 Lombok builder:
@Builder(toBuilder = true)
@Data
public class TaskSettings {
private List<Task> tasks;
public static class TaskSettingBuilder {
private List<Task> tasks = new ArrayList<>();
public TaskSettingBuilder longLivedTask(Duration duration) {
// construct long-lived task
tasks.add(new Task());
return this;
}
public TaskSettingBuilder shortLivedTask(Duration duration) {
// construct short-lived task
tasks.add(new Task());
return this;
}
}
}
我有一個自定義構建器,它可以獲取不同類型任務的信息、構造和適當的任務以添加到列表中。 這很好用,但是當我使用toBuilder
實現時,它使用原始列表而不是復制它。 因此,如果我向新實例添加一些內容,舊實例將被更新:
TaskSettings ts = TaskSettings.builder()
.longLivedTask(Duration.ofDays(365))
.build();
TaskSettings ts2 = ts.toBuilder().shortLivedTask(Duration.ZERO).build();
ts
現在將擁有短暫的任務。 我嘗試@Singular
注釋,但它生成了接受Task
object 而不是讓我構造它的構建器方法。 我知道我可以將任務構建移至Task
object 的構建器,但我想將其作為TaskSettings
的一部分。 我該如何做到這一點?
使用@Singular
或不使用 lombok。 如果您不使用@Singular
, List
沒有什么神奇之處。 這是一個領域。 像任何其他人一樣。
如果您沒有使用@Singular
,並且您的列表對象不是不可變的(您粘貼的代碼段中都是這種情況),那么這個問題可以概括為:
“ toBuilder()
進行淺克隆。但是,鑒於我的對象的字段本身是可變的,我需要一個深層克隆。如何讓 lombok 創建一個深層克隆?”
答案是:Lombok 不這樣做,也沒有簡單的方法讓它這樣做; java 土地上的深度克隆通常是個難題。 沒有很多簡單的方法可以做到這一點。 它要么是大量的跑腿工作(到處寫復制構造函數和clone()
impls),要么是hackery(序列化它,然后反序列化它),並且有很多未充分考慮的問題(深度克隆的重點只是為了避免方法調用者弄亂了 state 他們不應該弄亂,因此暗示不可變對象不需要被深度復制,例如)。
因此,向 Project Lombok 提出的功能請求是:“請讓深拷貝成為我可以打開的東西”是有問題的。 我們 lombok 的維護人員將如何滿足該請求?
使用@Singular
,列表本身現在是 lombok 的已知概念,lombok 將相應地采取行動。 它仍然不是深拷貝(即,如果你有一個@Singular List<List<String>>
,除非那些內部列表是不可變的,否則你仍然有麻煩),但列表將(或者如果不是,應該是,文件錯誤!)在您使用toBuilder()
並添加一些內容時被復制(使用@Singular
時獲得的列表是不可變的。如果它沒有更改,則無需復制它)。
我嘗試了@Singular 注釋,但它生成了接受任務 object 而不是讓我構造它的構建器方法。
這聽起來像你在這里如何使用各種 lombok 注釋時犯了一個錯誤,或者可能是 lombok 中的一個錯誤。 你能詳細說明嗎? 因為聽起來答案只是“在你的tasks
字段中扔@Singular
- 這就是你所需要的。 除非顯然您嘗試過,但結果並未如您所願。
我為此提出了一個新問題,代碼片段顯示了 lombok 最終做了什么以及你想要它做什么。
您應該查看@Builder.ObtainVia https://projectlombok.org/features/Builder
獲得Via 使您能夠創建具有來自其他地方的字段值的實例,例如來自另一個字段或方法的返回
@Builder(toBuilder = true)
@Data
public class TaskSettings {
@Builder.ObtainVia(method = "initTask") // important
private List<Task> tasks;
private List<Task> initTask() {
return new ArrayList<Task>();
}
//...
}
class Main {
public static void main(String[] args) {
TaskSettings ts = TaskSettings.builder()
.longLivedTask(Duration.ofDays(365))
.build();
System.out.println(ts.getTasks().size()); // 1
TaskSettings ts2 = ts.toBuilder().shortLivedTask(Duration.ZERO).build();
System.out.println(ts.getTasks().size()); // without ObtainVia print 2, with ObtainVia print 1
System.out.println(ts2.getTasks().size());// without ObtainVia print 2, with ObtainVia print 1
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.