Lombok: Builder.Default menyebabkan bidang menjadi nol saat membuat instance dengan yang baru

Dibuat pada 29 Mar 2017  ·  58Komentar  ·  Sumber: projectlombok/lombok

Saat menggunakan anotasi @Builder.Default pada daftar/set/peta dan membuat instance objek menggunakan kata kunci baru, bidangnya adalah nol.

<strong i="7">@Data</strong>
<strong i="8">@Builder</strong>
<strong i="9">@AllArgsConstructor</strong>
<strong i="10">@NoArgsConstructor</strong>
<strong i="11">@Entity</strong>
public class MyClass {

   @OneToMany(mappedBy = "orderItem", cascade = CascadeType.ALL)
   @Builder.Default
   private List<Entitlement> entitlements = new ArrayList<>();

}
// entitlements is null, should be empty ArrayList
MyClass myClass = new MyClass();

Komentar yang paling membantu

@rspilker Alasan untuk melakukan perubahan, yang mengarah ke masalah ini adalah untuk menghilangkan kemungkinan inisialisasi ganda, bukan? Hal ini dijelaskan di sini #1429.

Tapi, sungguh, inisialisasi ganda adalah masalah yang jauh lebih sedikit daripada perilaku yang sama sekali tidak terduga dalam memodifikasi inisialisasi default bidang POJO. Tentu saja, cara terbaik untuk menyelesaikannya adalah dengan menyingkirkan inisialisasi ganda dan tetap tidak merusak inisialisasi bidang. Tetapi jika ini tidak mungkin, atau terlalu sulit, atau terlalu lama, maka, buatlah inisialisasi ganda ini terjadi! Kemudian dokumentasikan ke @Builder.Default javadocs dalam huruf tebal dan banyak orang akan mengucapkan terima kasih!

Ya, ini dapat menyebabkan masalah jika seseorang menggunakan beberapa penginisialisasi bidang yang canggih, tetapi ini jauh lebih jarang terjadi, daripada masalah dari bidang yang dibatalkan secara tidak terduga. MENURUT OPINI SAYA.

Setidaknya, dokumentasikan perilaku bidang-penghapusan ini dalam @Builder.Default javadocs dalam font peringatan merah besar . Perilaku ini benar-benar mengejutkan dan sulit ditemukan ketika NPE dilemparkan.

Semua 58 komentar

Masalah ini juga terjadi dengan jenis non-primitif lainnya, tidak hanya daftar/set/peta.

```#java
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Pembangun
@ToString(panggilanSuper = benar)
Tes kelas publik {

public static final int DEFAULT_INT = 42;

public enum Status {
    STATUS_ONE,
    STATUS_TWO;
}

@Builder.Default
private Integer someInt = DEFAULT_INT;

@Builder.Default
private Status currentStatus = Status.STATUS_ONE;

public static void main(String[] args) {
    Test test = new Test();
    System.out.println("test = " + test);
}

}
```

Masalah ini membuat Rilis 1.16.16 sama sekali tidak dapat digunakan bagi kami. Semoga ini diperbaiki di Rilis berikutnya karena kami benar-benar dapat menggunakan Anotasi @Builder.Default .

Apakah ada rencana untuk memperbaiki ini? Sejujurnya, ini adalah masalah BESAR karena sangat tidak intuitif dan menimbulkan bug yang sangat sulit ditemukan. Sejujurnya, cara paling intuitif untuk menghasilkan nilai default untuk builder adalah dengan mengambil nilai dari inisialisasi bidang, alih-alih memerlukan anotasi Builder.Default tambahan.

Dari sekilas melihat kode sumber, saya menemukan bahwa @Builder.Default menghapus bagian inisialisasi dari setiap bidang beranotasi. Baris 585:
https://github.com/rzwitserloot/lombok/blob/e92e285d95e0fb08c32e7059f85806a30985084b/src/core/lombok/javac/handlers/HandleBuilder.java#L580 -L590

Apa tujuan menghapus inisialisasi ini? Apakah karena efek samping potensial dari ekspresi inisialisasi?

@joadelgado Lihat di sini . Inisialisasi telah dipindahkan ke pembuat jadi jika Anda tidak membatalkan bidang itu akan diinisialisasi dua kali.

@omega09 dalam hal ini saya akan mengatakan @NoArgsConstructor (dan serupa) harus dikonversi untuk mengatur bidang juga. Karena itu, ini menyebabkan bug aneh dan membuat anotasi @Builder berbahaya. Ini jelas merupakan pelanggaran paling tidak mengejutkan, karena menghapus fitur tingkat bahasa yang umum digunakan.

Saya menduga builder hanya dipertimbangkan secara terpisah, tetapi seringkali berguna untuk memiliki @NoArgsConstructor dan builder. Satu kasus penggunaan adalah ketika bekerja dengan ORM atau JSON (di mana perpustakaan sering membutuhkan konstruktor tanpa argumen). Lain adalah pengujian (di mana kode utama dapat menggunakan konstruktor tetapi tes menggunakan pembangun).

Untuk saat ini, sepertinya satu-satunya solusi adalah menulis konstruktor no-args-secara manual, yang menyusahkan.

menulis konstruktor secara manual juga berarti bahwa anotasi kendala seperti @Nonnull harus diproses secara manual di sana juga, yang tidak terlalu elegan.

Adakah rencana untuk memperbaiki perilaku @Builder.default saat ini?

@davidje13 Dalam hal ini, tuliskan pendapat Anda tentang PR kepada orang yang memiliki otoritas dan bukan kepada saya, yang baru saja menjelaskan alasannya kepada seseorang yang bertanya tentang detail implementasi.

Untuk membersihkan inisialisasi harus dilakukan dalam kombinasi dengan bidang akhir (seperti saat menerapkan Nilai) tetapi tidak untuk anggota non-final seperti saat menggabungkan Builder dengan Data, imho.

Ada pembaruan?

Kami benar-benar membutuhkan masalah ini untuk diselesaikan. Kami tidak dapat memperbarui ke versi yang lebih baru karena ini dan sekarang kami juga mendapatkan konflik dengan lib baru lainnya, misalnya Jackson >2.9. Jadi kami tidak dapat memperbarui jackson karena kami tidak dapat memperbarui lombok dan sebagainya.

Ini benar-benar masalah bagi kami karena kami memiliki banyak kelas, misalnya objek nilai dengan beberapa bidang yang diinisialisasi, yang menggunakan anotasi pembangun serta konstruktor. Bahkan menulis konstruktor secara manual tidak akan memperbaiki masalah ini, karena @Builder.Default tampaknya menghapus inisialisasi.

Bisakah kami memiliki umpan balik tentang ini?
Terima kasih

Tampaknya berfungsi jika Anda menulis konstruktor no args secara manual. Saya tidak punya masalah. Saya setuju ini harus diselesaikan secepatnya.
Bagi saya itu menyebabkan banyak masalah ketika dipasangkan dengan DBFlow v3, karena menggunakan konstruktor untuk membuat objek di kelas yang dihasilkan.

Tetapi hanya jika Anda menduplikasi bidang default lagi di konstruktor default... Konstruktor default kosong tidak akan berfungsi.

Ya itu benar. Jika Anda menggunakan anotasi @NoArgsConstructor (atau menulis konstruktor no args secara manual tetapi tidak menginisialisasi bidang), Anda akan menghadapi banyak masalah.

Apakah ada pembaruan tentang ini? Sepertinya solusi termudah adalah tidak menghapus instantiasi asli. Dengan begitu, NoArgsConstructor default akan mengambil instance variabel bidang Anda dengan benar dan metode builder.build() Anda hanya akan memanggil target "default" yang dihasilkan.

Apakah ada orang yang bekerja pada yang satu ini? Kami memiliki efek samping yang sangat aneh ketika menggunakan Lombok bersamaan dengan JPA. Referensi daftar dibatalkan saat menggunakan @Builder.Default .

Ya, kami sedang menyelidiki ini.

@rspilker Alasan untuk melakukan perubahan, yang mengarah ke masalah ini adalah untuk menghilangkan kemungkinan inisialisasi ganda, bukan? Hal ini dijelaskan di sini #1429.

Tapi, sungguh, inisialisasi ganda adalah masalah yang jauh lebih sedikit daripada perilaku yang sama sekali tidak terduga dalam memodifikasi inisialisasi default bidang POJO. Tentu saja, cara terbaik untuk menyelesaikannya adalah dengan menyingkirkan inisialisasi ganda dan tetap tidak merusak inisialisasi bidang. Tetapi jika ini tidak mungkin, atau terlalu sulit, atau terlalu lama, maka, buatlah inisialisasi ganda ini terjadi! Kemudian dokumentasikan ke @Builder.Default javadocs dalam huruf tebal dan banyak orang akan mengucapkan terima kasih!

Ya, ini dapat menyebabkan masalah jika seseorang menggunakan beberapa penginisialisasi bidang yang canggih, tetapi ini jauh lebih jarang terjadi, daripada masalah dari bidang yang dibatalkan secara tidak terduga. MENURUT OPINI SAYA.

Setidaknya, dokumentasikan perilaku bidang-penghapusan ini dalam @Builder.Default javadocs dalam font peringatan merah besar . Perilaku ini benar-benar mengejutkan dan sulit ditemukan ketika NPE dilemparkan.

Saya sangat setuju dengan @xak2000.

Saya bahkan akan melangkah lebih jauh dan mengatakan bahwa @Builder.Default berbahaya karena pembatalan tidak cukup didokumentasikan dan itu sama sekali tidak intuitif.

Lombok memang hebat tapi ini perlu diperbaiki. Apakah sudah ada permintaan tarik? Kalau tidak, saya bisa menjadi sukarelawan untuk satu.

Intinya adalah bahwa @Builder.Default adalah kelas bersarang dari anotasi @Builder , mengapa Anda menganggapnya berfungsi dengan yaitu @NoArgsConstructor karena ini bukan anotasi @Builder dan mereka bahkan tidak berhubungan?

Sudah jelas, jadi hanya ada dua solusi:

  • Refactor @Builder.Default sebagai @Default dan tambahkan dukungan untuk semua kelas konstruktor dengan efek yang sama untuk menghapus inisialisasi bidang yang melanggar kode saat ini,
  • Berhenti mengandalkan @Builder.Default dalam kasus konstruktor yang bahkan mungkin tidak dirancang untuk bekerja sama dengan mereka

Jelas? Mengapa menjadi jelas bahwa dua anotasi tidak bekerja satu sama lain, ketika tidak didokumentasikan? Sangat sepele bagi pemroses anotasi untuk memeriksa apakah anotasi lain ada dan membawa nilainya. Ini tidak seperti @Builder.Default bersifat pribadi.

Yang sedang berkata, saya akan mencoba memperbaiki ini ketika saya sampai ke komputer.

@NeveHanter ini bahkan bukan ketidakcocokan dengan @NoArgsConstructor tetapi hanya dengan konstruktor yang dideklarasikan secara manual juga. Jika saya membuat instance kelas tanpa melalui builder, nilai default akan diabaikan. Itu bermasalah dalam hal apa pun di mana kelas dapat dipakai tanpa pembangun.

@NeveHanter Dalam hal ini saya menggunakan pendekatan ini .

@rspilker , apakah anda sudah punya solusi? Jika tidak, saya juga memilih untuk mengabaikan pendekatan saat ini untuk memindahkan ekspresi init ke suatu metode (juga mempertimbangkan # 1749), karena dalam kebanyakan kasus, dampak memori/kinerja harus minimal.

Jika Anda benar-benar ingin tetap berpegang pada pendekatan saat ini, mungkin ini bisa menjadi cara untuk pergi:

  • Alih-alih memindahkan ekspresi inisialisasi ke metode statis, hapus dari deklarasi variabel dan tambahkan tugas ke bagian atas konstruktor (menggunakan Handler prioritas sangat rendah, jadi anotasi lombok lainnya sudah selesai menghasilkan konstruktornya). Tambahkan juga ke konstruktor yang diimplementasikan secara manual.
  • Apakah _not_ menambahkan tugas ini ke konstruktor yang selalu secara eksplisit memberikan nilai ke variabel instan.
  • Biarkan @Builder menghasilkan konstruktor (pribadi) dengan instance builder sebagai satu-satunya parameter. Gunakan private boolean var$set untuk memutuskan apakah akan menggunakan ekspresi init atau nilai dalam instance builder. Juga jangan tambahkan tugas ke konstruktor ini.

Kekurangan:

  • @Builder tidak akan menghasilkan @AllArgsConstructor lagi. Ini bisa merusak kode yang ada. Namun, saya menganggap ini lebih baik.
  • Mungkin tidak mudah untuk mengetahui apakah konstruktor selalu memberikan nilai ( if s, exit awal, dll.).
  • Pendekatan ini akan mengubah urutan inisialisasi jika hanya ada beberapa variabel instan yang dianotasi dengan @Builder.Default . (Perhatikan bahwa ini juga terjadi sekarang.) Dalam contoh berikut, nilai k akan menjadi 0 (bukan 1 , seperti yang Anda harapkan) , karena inisialisasi k akan dieksekusi sebelum inisialisasi j dalam konstruktor:
class Test {
    @Builder.Default
    int j = 1;
    int k = j;
}

@janrieke tidak dapat diterapkan; kami tidak memiliki kemampuan untuk membuat salinan lengkap dari simpul arbitrer. Setiap simpul ekspresi yang diberikan dapat menjadi kompleks sewenang-wenang:

Object x = new Object() {
    /* absolutely all valid java nodes imaginable can go in here */
};

jadi membuat 'pengganda ekspresi' adalah pekerjaan beberapa bulan.

Anda akan berpikir AST itu sendiri memiliki kemampuan untuk menyalin setiap node dengan bersih, tapi ... mereka tidak. Kami telah mencobanya sebelumnya dan tampaknya berhasil, tetapi kemudian rusak dengan cara yang aneh dan tidak terduga karena node itu sendiri juga membawa beberapa resolusi dan info nomor baris dan itu TIDAK boleh diduplikasi.

Jadi, Anda tahu. Ide yang hebat. Kami juga memilikinya. Tetapi... :(

Diatasi dengan menghasilkan sesuatu seperti: "this.x = TypeName.$default$x();" secara eksplisit di konstruktor no-args yang dihasilkan, yang merupakan yang terbaik yang bisa kita lakukan di sini. Harus mengatasi semua masalah, kan?

rilis tepi tersedia dengan pembaruan ini: https://projectlombok.org/download-edge

Terima kasih Ronald!

Bagus, itu harus memperbaiki sebagian besar masalah. Saya akan mengadaptasinya ke @SuperBuilder (yang saat ini menyimpan ekspresi init pada variabel instan).

Yang tersisa adalah mungkin masih mengejutkan (walaupun sekarang didokumentasikan) bahwa inisialisasi tidak akan dilakukan untuk konstruktor manual.
Jadi bisakah menyuntikkan tugas dengan pemanggilan metode sebagai rhs di awal setiap konstruktor manual menjadi solusi (tentu saja hanya untuk konstruktor yang tidak menetapkan nilai sendiri)?

@rzwitserloot Perbaikan ini merupakan peningkatan dari situasi saat ini, tetapi seperti yang dinyatakan @janrieke , masalah masih ada untuk konstruktor manual. @rspilker menyebutkan di https://github.com/rzwitserloot/lombok/pull/1429#issuecomment -312095098 bahwa masalah asli, mengapa kode penginisialisasi dihapus, adalah tentang kemungkinan inisialisasi ganda yang mahal. Saya pikir operasi kompleks ini pada inisialisasi, sementara juga menggunakan pola pembangun, harus dianggap sebagai kasus tepi yang jarang dan dalam kebanyakan situasi inisialisasi ganda ini seharusnya tidak menjadi masalah. Mungkin Anda dapat memperkenalkan parameter anotasi pada Builder.Default untuk menyisih dari atau (untuk mencegah perubahan yang rusak) untuk ikut serta dalam inisialisasi ganda.

@rzwitserloot Bagus, terima kasih! Berapa lama biasanya waktu yang dibutuhkan untuk rilis tepi seperti itu tersedia di maven central (alias stabil)?

Masalah ini sepertinya tidak diperbaiki dalam rilis 1.18.2 terakhir?
Menggunakan plugin IntelliJ lombok versi 0.18-2018-1 atau 0.19-2018-1
Menggunakan org.proj ectlombok:lombok-maven-plugin :1.18.0.0
Menggunakan pakar 3.5.3

Tidak berfungsi baik di IntelliJ atau langsung di baris perintah mvn.
Kelas yang dihasilkan sebagai konstruktor kosong dengan Builder.Default digunakan pada daftar = new ArrayList<>();

Masalah ini diperbaiki di versi 1.18.2

<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.2</version> </dependency>

`impor lombok.AllArgsConstructor;
impor lombok.Builder;
impor lombok.Data;
impor lombok.NoArgsConstructor;

@Data
@Pembangun
@NoArgsConstructor
@AllArgsConstructor
Tes kelas publik {
public int static final DEFAULT_INT = 42;
status enum publik {
STATUS_ONE,
STATUS_DUA;
}
@Pembangun.Default
private Integer someInt = DEFAULT_INT;

@Builder.Default
private Status currentStatus = Status.STATUS_ONE;

public static void main(String[] args) {
    Test test = new Test();
    System.out.println("test = " + test);
}

}`

Hasil:
test = Test(someInt=42, currentStatus=STATUS_ONE)

Saya percaya ini masih tidak berfungsi sebagaimana dimaksud.

Ini adalah kelas Person :

<strong i="8">@Data</strong>
<strong i="9">@Builder</strong>
<strong i="10">@NoArgsConstructor</strong>
<strong i="11">@AllArgsConstructor</strong>
public class Person {

  @Builder.Default
  private String name = "John Doe";

  @Builder.Default
  private int age = 25;

  public Person(final String name) {
    this.name = name;
  }
}

Dan kelas sederhana untuk mencetak kemungkinan kombinasi:

public class PersonTest {
  public static void main(final String[] args) {
    System.out.println(new Person()); // Person(name=John Doe, age=25)
    System.out.println(new Person("John Watson")); // Person(name=John Watson, age=0)
    System.out.println(new Person("Sherlock Holmes", 30)); // Person(name=Sherlock Holmes, age=30)
    System.out.println(Person.builder().build()); // Person(name=John Doe, age=25)
    System.out.println(Person.builder().name("Jane Doe").build()); // Person(name=Jane Doe, age=25)
    System.out.println(Person.builder().name("Jane Doe").age(18).build()); // Person(name=Jane Doe, age=18)
  }
}

Perhatikan contoh kedua di mana usia adalah 0. Saya yakin ini adalah bug dan seharusnya 25. Jika Anda menghapus anotasi @Builder dan @Builder.Default (dan tentu saja contoh pembuat yang tidak dikompilasi) contoh kedua akan mengatur usia ke 25 seperti yang diharapkan.

Saya telah menjalankan contoh-contoh ini dengan versi 1.18.2.

@alturkovic , Anda benar. Ini adalah bug lain yang jelas.
Setidaknya sekarang, itu memecahkan anotasi NoArgsConstructor.

Gan. Aku akan gila.
Kami memutuskan untuk tidak menggunakan @Builder.Default untuk bug aneh yang diperkenalkannya.
Jadi alih-alih kami menggunakan kerangka untuk kelas pembangun yang menginisialisasi bidang.

Sekarang lombok mengeluarkan peringatan " @Builder akan mengabaikan ekspresi inisialisasi sepenuhnya. Jika Anda ingin ekspresi inisialisasi berfungsi sebagai default, tambahkan @Builder.Default. Jika tidak seharusnya disetel selama membangun, buat bidang menjadi final."
Karena kami telah mengonfigurasi build kami agar gagal pada peringatan (untuk menjaga kode kami tetap bersih), ini adalah masalah nyata bagi kami.
Adakah cara untuk menonaktifkan peringatan itu?

Iya @eekboom. Pilihan terbaik adalah tidak menggunakan Builder.Default ATM. Namun, Anda dapat mencapai fungsi yang sama (seperti yang kami lakukan) dengan pendekatan yang dijelaskan di sini .

Saya sadar bahwa ini masih menjadi masalah bagi konstruktor manual (sekarang untuk @Builder dan @SuperBuilder ). Dalam posting sebelumnya saya menyarankan solusi yang mungkin, yang menurut saya dapat diterapkan dan tidak memiliki terlalu banyak kekurangan.
Kami membutuhkan penjelasan dari pengelola di sini tentang cara melanjutkan.

Ada pembaruan tentang ini? Menghabiskan terlalu banyak waktu hari ini untuk mencoba mencari tahu mengapa bidang @Builder.Default saya nol saat menggunakan konstruktor saya sendiri.

Anda dapat mencoba solusi ini sebagai solusi hingga perbaikan dirilis.

@goostleek - Saya mencoba solusi itu, tetapi kemudian menyadari bahwa kelas kami yang menggunakan @Builder juga menggunakan @Singular , yang memecah kode kami yang ada yang mengasumsikan keberadaan bidang pembangun tunggal. Apakah ada beberapa solusi yang menjelaskan keberadaan bidang @Singular ?

Saya tidak bisa melihat masalahnya. Bisakah Anda memberikan MWE (dengan unit test) untuk masalah tersebut?

wah solusinya gampang gan...

Bagi siapa saja yang perlu menggunakan @Singular sehubungan dengan solusi yang diusulkan dalam komentar StackOverflow yang ditautkan sebelumnya , lakukan ini:

<strong i="9">@Getter</strong>
<strong i="10">@Setter</strong>
<strong i="11">@NoArgsConstructor</strong>
public class SearchRequest {
    // This is the field I want to default
    private Context context = Context.default;

    // <strong i="12">@Singular</strong>
    // We had a singular here, but it will no longer work since the <strong i="13">@Builder</strong> annotation 
    // was moved from the `public class` above to the below private constructor
    private List<SearchFilter> filters = new ArrayList<>();

    <strong i="14">@Builder</strong>
    private SearchRequest(SearchContext context,
                          // move your <strong i="15">@Singular</strong> annotation here
                          <strong i="16">@Singular</strong> List<RequestFilter> filters) { 
        this.searchContext = Optional.ofNullable(context).orElse(this.searchContext);
        this.filters = filters;
    }
}

~ Bagus! Saya telah memperbarui jawaban SO dengan merujuk solusi Anda di komentar 👍 .~

Saya melihat Anda sudah melakukannya, menghapus ...

Apakah masalah ditemukan di https://github.com/rzwitserloot/lombok/issues/1347#issuecomment -415328497 dilacak dalam tiket tertutup ini, atau apakah ada tiket terpisah yang dibuat untuk edisi baru?

Ada diskusi di forum tentang bagaimana konstruktor manual dapat dimodifikasi untuk mengurangi masalah itu: https://groups.google.com/forum/#!topic/project -lombok/e9PzKXRlXXA
Di dalamnya, @rzwitserloot memberikan beberapa contoh di mana tidak ada solusi yang bagus. Mengutip dia: "melakukannya dengan benar tampaknya sangat mustahil bagi saya".

Jadi, saya memilih untuk hanya mengeluarkan peringatan jika tidak ada penugasan ke bidang itu di konstruktor manual. Anda harus memperbaiki peringatan dengan menambahkan tugas. Menurut pendapat saya, ini akan mencegah sebagian besar bug. Kekurangannya adalah jika Anda _secara sengaja_ menginginkannya tidak diinisialisasi, Anda harus menambahkan baris yang tidak perlu; namun, baris ini membuat kode lebih mudah dipahami oleh pengguna non-ahli lombok.
Tapi semuanya terserah pengelola lombok disini.

Akan lebih baik untuk menghapus semua fitur, itu berbahaya dan menyebabkan bug yang sangat sulit dilacak. Taruhan terbaik adalah menghindarinya IMHO.

@Builder.Default dan konstruktor khusus tidak kompatibel ((

Saya tidak memerlukan verifikasi bahwa semua bidang @Builder telah disetel.

Tetapi saya ingin memiliki metode cetak biru dengan @Builder(toBuilder = true) .

Jadi saya menulis ulang kode dengan konstruktor diganti dengan of dengan pembangun:

<strong i="13">@Builder</strong>
public class Connection {
    private String user;
    private String pass;

    @Builder.Default
    private long timeout = 10_000;

    @Builder.Default
    private String port = "8080";

    public static Connection of(String user, String pass) {
        return Connection.builder()
            .user(user)
            .pass(pass)
            .build();
    }

    public static Connection of(String user, String pass, String port) {
        return Connection.builder()
            .user(user)
            .pass(pass)
            .port(port)
            .build();
    }

    public static Connection of(String user, String pass, String port, long timeout) {
        return Connection.builder()
            .user(user)
            .pass(pass)
            .port(port)
            .timeout(timeout)
            .build();
    }
}

Sayang sekali saya terpaksa membuat objek Builder alih-alih objek tunggal dengan new ((

@gavenkoa Saya pasti setuju bahwa ada sesuatu yang salah, tetapi solusi Anda tampaknya terlalu rumit untuk variabel n , Anda memerlukan baris O(n²) . Saya pikir, Anda dapat mendefinisikan @Wither dan menggunakan

    public static Connection of(String user, String pass, String port, long timeout) {
        return Connection.of(user, pass).withTimeout(timeout);
    }

tapi ini akan menciptakan lebih banyak sampah. Tapi bagaimana dengan setter yang dirantai seperti

    public static Connection of(String user, String pass, String port, long timeout) {
        return Connection.of(user, pass).setTimeout(timeout);
    }

? Tentu, itu masih O(n²) , tetapi bukan garis.

Sebenarnya, dengan objek yang bisa berubah, saya selalu bertanya-tanya untuk apa orang membutuhkan pembangun?

@Maaartinus @Wither masih fitur eksperimental. Documents mengatakan bahwa mereka bahkan dapat mengubah nama ((

Saya tidak membutuhkan pembangun, saya hanya suka chaining dan setter chaining break Bean API ((

@gavenkoa Anda benar tentang @Wither menjadi eksperimental. Tapi itu eksperimental sejak 2012 dan tidak ada yang datang dengan nama yang lebih baik sejak itu. Ini salah satu favorit saya.

@rzwitserloot IMHO, @Wither harus dipromosikan dari eksperimental, WDYT?

setter chaining memutus Bean API

Jadi begitu. Dengan kacang polong, tidak ada solusi. Tim Lombok menolak untuk menerapkan kedua jenis setter karena ini adalah API yang jelek (dan saya setuju; menyembuhkan lebih buruk daripada penyakit). Dengan Builder, itu jelek dengan cara yang berbeda, mungkin lebih baik.

Kami berencana untuk melakukan beberapa pekerjaan pada @Wither segera. Jadi itu akan tinggal di eksperimental untuk sementara waktu.

Idenya adalah untuk meningkatkan kegunaan untuk Struktur Data Persisten.

Kami sedang mempertimbangkan alternatif berikut, mungkin kami dapat mendukung semua,

<strong i="9">@RequiredArgsConstructor</strong>
class Point {
  <strong i="10">@Wither</strong> final int x;
  final int y;
}
class Point {
  final int x;
  final int y;

  Point(int x, int y) {
    this.x = x;
    this.y = y;
  }

  // Current implementation
  Point withX(int x) {
    return new Point(x, this.y);
  }

  // Alternative 1
  Point withX(Function<Integer, Integer> xFunction) {
    return new Point(xFunction.apply(this.x), this.y);
  }

  // Alternative 2
  Point withX(Function<Point,Integer> xFunction) {
    return new Point(xFunction.apply(this) this.y);
  }
}

Ini adalah sejarah komentar yang panjang dan rumit. Apakah masalah ini ditutup karena tidak akan diperbaiki? Saya pasti mengalami masalah ini dan saat ini mencoba

Saat ini saya dapat menggunakan @NoArgsConstructor dan @Builder dengan @Builder.Default dan beberapa konstruktor lain dengan cara ini:

<strong i="9">@NoArgsConstructor</strong>
<strong i="10">@AllArgsConstructor</strong>
<strong i="11">@Builder</strong>
public SomeClass {
  @Builder.Default
  private int someInt = 0;
  @Builder.Default
  private String someString = "initial value";

  public SomeClass(int someInt) {
    this();
    this.someInt = someInt;
  }
}

Dengan cara ini ketiga konstruktor dan pembangun menginisialisasi bidang dengan benar.

Versi lombok saya adalah 1.18.2

@asserebryanskiy trik keren – sayangnya, tidak berfungsi untuk bidang akhir.

@jasonCodesAway tidak, itu ditutup karena sudah diperbaiki. Namun, saat ini konstruktor yang ditulis secara manual masih mengalami kurangnya masalah nilai default. Satu-satunya perbaikan adalah kita masuk ke sana dan menambahkan baris secara manual yang rumit, tetapi @janrieke punya rencana. Kami akan membicarakannya saat berikutnya kami melakukan triase bug dan fitur. Pembukaan kembali, khusus untuk __MANUALLY__ konstruktor tertulis.

Akan sulit untuk melakukan ini dengan benar, lihat komentar di https://groups.google.com/forum/#!topic/project -lombok/e9PzKXRlXXA – tetapi setidaknya kita harus berupaya mendeteksi bahwa ini sedang terjadi (konstruktor manual merujuk ke bidang dengan anotasi default di sana) dan mengeluarkan peringatan.

Bagaimana kalau membuat bug baru untuk itu? Baik judulnya bukan
deskripsi masalah benar-benar cocok dengan masalah yang tersisa;)

Pada Jumat, 17 Januari 2020, 04:24 Reinier Zwitserloot [email protected]
menulis:

@jasonCodesAway https://github.com/jasonCodesAway tidak, itu ditutup
karena sudah fix. Namun, sekarang konstruktor yang ditulis secara manual melakukannya
masih mengalami kurangnya masalah nilai default. Satu-satunya perbaikan adalah bagi kita untuk
masuk ke sana dan tambahkan baris secara manual yang rumit, tetapi @janrieke
https://github.com/janrieke punya rencana. Kita akan membicarakannya lain kali
kami melakukan triase bug dan fitur. Pembukaan kembali, khusus untuk MANUAL
konstruktor tertulis.


Anda menerima ini karena Anda berlangganan utas ini.
Balas email ini secara langsung, lihat di GitHub
https://github.com/rzwitserloot/lombok/issues/1347?email_source=notifications&email_token=AABIERLIPOJ7YSZEIEROM73Q6EQINA5CNFSM4DFS7BUKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LN5WXHJKT44Jissue
atau berhenti berlangganan
https://github.com/notifications/unsubscribe-auth/AABIERMMFBWMZKOXK4GE65TQ6EQINANCNFSM4DFS7BUA
.

Pindah ke fitur baru #2340

Apakah halaman ini membantu?
0 / 5 - 0 peringkat