JavaRush /Java Blog /Random-ID /Rehat kopi #128. Panduan Catatan Java

Rehat kopi #128. Panduan Catatan Java

Dipublikasikan di grup Random-ID
Sumber: abhinavpandey.dev Dalam tutorial ini, kita akan membahas dasar-dasar penggunaan Records di Java. Catatan diperkenalkan di Java 14 sebagai cara untuk menghapus kode boilerplate di sekitar pembuatan objek Nilai sambil memanfaatkan objek yang tidak dapat diubah. Rehat kopi #128.  Panduan Catatan Java - 1

1. Konsep dasar

Sebelum kita masuk ke entri itu sendiri, mari kita lihat masalah yang dipecahkannya. Untuk melakukan ini, kita harus mengingat bagaimana objek nilai dibuat sebelum Java 14.

1.1. Nilai benda

Objek nilai merupakan bagian integral dari aplikasi Java. Mereka menyimpan data yang perlu ditransfer antar lapisan aplikasi. Objek nilai berisi bidang, konstruktor, dan metode untuk mengakses bidang tersebut. Di bawah ini adalah contoh objek nilai:
public class Contact {
    private final String name;
    private final String email;

    public Contact(String name, String email) {
        this.name = name;
        this.email = email;
    }

    public String getName() {
        return name;
    }

    public String getEmail() {
        return email;
    }
}

1.2. Kesetaraan antar objek Nilai

Objek nilai juga dapat memberikan cara untuk membandingkannya demi kesetaraan. Secara default, Java membandingkan kesetaraan objek dengan membandingkan alamat memorinya. Namun, dalam beberapa kasus, objek yang berisi data yang sama dapat dianggap sama. Untuk mengimplementasikan ini, kita dapat mengganti metode sama dengan dan .hashCode . Mari kita implementasikan untuk kelas Contact :
public class Contact {

    // ...

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Contact contact = (Contact) o;
        return Object.equals(email, contact.email) &&
                Objects.equals(name, contact.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, email);
    }
}

1.3. Kekekalan objek Nilai

Objek nilai harus tidak dapat diubah. Artinya kita harus membatasi cara kita mengubah bidang suatu objek. Hal ini disarankan karena alasan berikut:
  • Untuk menghindari risiko perubahan nilai bidang secara tidak sengaja.
  • Untuk memastikan bahwa objek yang sama tetap sama sepanjang hidup mereka.
Karena kelas Kontak sudah tidak dapat diubah, sekarang kita:
  1. menjadikan bidang itu pribadi dan final .
  2. hanya menyediakan pengambil untuk setiap bidang (tidak ada penyetel ).

1.4. Mendaftarkan objek Nilai

Seringkali kita perlu mendaftarkan nilai-nilai yang terkandung dalam objek. Hal ini dilakukan dengan menyediakan metode toString . Setiap kali suatu objek didaftarkan atau dicetak, metode toString dipanggil . Cara termudah di sini adalah dengan mencetak nilai setiap bidang. Berikut ini contohnya:
public class Contact {
    // ...
    @Override
    public String toString() {
        return "Contact[" +
                "name='" + name + '\'' +
                ", email=" + email +
                ']';
    }
}

2. Kurangi template dengan Records

Karena sebagian besar objek nilai memiliki kebutuhan dan fungsi yang sama, alangkah baiknya jika proses pembuatannya disederhanakan. Mari kita lihat bagaimana rekaman membantu mencapai hal ini.

2.1. Mengonversi kelas Person menjadi Record

Mari kita buat entri kelas Kontak yang memiliki fungsi yang sama dengan kelas Kontak yang didefinisikan di atas.
public record Contact(String name, String email) {}
Kata kunci record digunakan untuk membuat kelas Record . Catatan dapat diproses oleh pemanggil dengan cara yang sama seperti kelas. Misalnya untuk membuat instance entri baru, kita dapat menggunakan kata kunci new .
Contact contact = new Contact("John Doe", "johnrocks@gmail.com");

2.2. Perilaku Default

Kami telah mengurangi kode menjadi satu baris. Mari kita daftar apa saja yang termasuk di dalamnya:
  1. Bidang nama dan email bersifat pribadi dan final secara default.

  2. Kode tersebut mendefinisikan "konstruktor kanonik" yang menggunakan bidang sebagai parameter.

  3. Bidang dapat diakses melalui metode seperti pengambil - name() dan email() . Tidak ada penyetel untuk bidang, sehingga data dalam objek menjadi tidak dapat diubah.

  4. Menerapkan metode toString untuk mencetak bidang seperti yang kami lakukan untuk kelas Kontak .

  5. Menerapkan metode sama dengan dan .hashCode . Mereka menyertakan semua bidang, seperti kelas Contact .

2.3 Konstruktor kanonik

Konstruktor default mengambil semua bidang sebagai parameter masukan dan menetapkannya ke bidang. Misalnya, Konstruktor Canonical default ditunjukkan di bawah ini:
public Contact(String name, String email) {
    this.name = name;
    this.email = email;
}
Jika kita mendefinisikan konstruktor dengan tanda tangan yang sama di kelas rekaman, konstruktor tersebut akan digunakan sebagai pengganti konstruktor kanonik.

3. Bekerja dengan catatan

Kita dapat mengubah perilaku entri dalam beberapa cara. Mari kita lihat beberapa kasus penggunaan dan cara mencapainya.

3.1. Mengganti implementasi default

Implementasi default apa pun dapat diubah dengan menimpanya. Misalnya, jika kita ingin mengubah perilaku metode toString , maka kita bisa menggantinya di antara kurung kurawal {} .
public record Contact(String name, String email) {
    @Override
    public String toString() {
        return "Contact[" +
                "name is '" + name + '\'' +
                ", email is" + email +
                ']';
    }
}
Demikian pula, kita dapat mengganti metode sama dengan dan kode hash .

3.2. Kit konstruksi kompak

Terkadang kita ingin konstruktor melakukan lebih dari sekadar menginisialisasi kolom. Untuk melakukan ini, kita dapat menambahkan operasi yang diperlukan ke entri kita di Compact Constructor. Disebut ringkas karena tidak perlu menentukan inisialisasi bidang atau daftar parameter.
public record Contact(String name, String email) {
    public Contact {
        if(!email.contains("@")) {
            throw new IllegalArgumentException("Invalid email");
        }
    }
}
Perhatikan bahwa tidak ada daftar parameter, dan inisialisasi nama dan email terjadi di latar belakang sebelum pemeriksaan dilakukan.

3.3. Menambahkan Konstruktor

Anda dapat menambahkan beberapa konstruktor ke sebuah rekaman. Mari kita lihat beberapa contoh dan batasannya. Pertama, mari tambahkan konstruktor baru yang valid:
public record Contact(String name, String email) {
    public Contact(String email) {
        this("John Doe", email);
    }

    // replaces the default constructor
    public Contact(String name, String email) {
        this.name = name;
        this.email = email;
    }
}
Dalam kasus pertama, konstruktor default diakses menggunakan kata kunci this . Konstruktor kedua menggantikan konstruktor default karena memiliki daftar parameter yang sama. Dalam hal ini, entri itu sendiri tidak akan membuat konstruktor default. Ada beberapa batasan pada konstruktor.

1. Konstruktor default harus selalu dipanggil dari konstruktor lainnya.

Misalnya, kode di bawah ini tidak dapat dikompilasi:
public record Contact(String name, String email) {
    public Contact(String name) {
        this.name = "John Doe";
        this.email = null;
    }
}
Aturan ini memastikan bahwa bidang selalu diinisialisasi. Juga dijamin bahwa operasi yang ditentukan dalam konstruktor kompak selalu dijalankan.

2. Tidak mungkin mengganti konstruktor default jika konstruktor kompak ditentukan.

Ketika konstruktor kompak ditentukan, konstruktor default secara otomatis dibuat dengan inisialisasi dan logika konstruktor kompak. Dalam hal ini, kompiler tidak akan mengizinkan kita mendefinisikan konstruktor dengan argumen yang sama dengan konstruktor default. Misalnya, dalam kode ini kompilasi tidak akan terjadi:
public record Contact(String name, String email) {
    public Contact {
        if(!email.contains("@")) {
            throw new IllegalArgumentException("Invalid email");
        }
    }
    public Contact(String name, String email) {
        this.name = name;
        this.email = email;
    }
}

3.4. Menerapkan Antarmuka

Seperti halnya kelas mana pun, kita dapat mengimplementasikan antarmuka dalam rekaman.
public record Contact(String name, String email) implements Comparable<Contact> {
    @Override
    public int compareTo(Contact o) {
        return name.compareTo(o.name);
    }
}
Catatan penting. Untuk memastikan kekekalan yang lengkap, catatan tidak dapat diwariskan. Entri bersifat final dan tidak dapat diperluas. Mereka juga tidak bisa memperluas kelas lain.

3.5. Menambahkan Metode

Selain konstruktor, yang mengesampingkan metode dan implementasi antarmuka, kita juga dapat menambahkan metode apa pun yang kita inginkan. Misalnya:
public record Contact(String name, String email) {
    String printName() {
        return "My name is:" + this.name;
    }
}
Kami juga dapat menambahkan metode statis. Misalnya, jika kita ingin memiliki metode statis yang mengembalikan ekspresi reguler yang dapat digunakan untuk memeriksa email, maka kita dapat mendefinisikannya seperti yang ditunjukkan di bawah ini:
public record Contact(String name, String email) {
    static Pattern emailRegex() {
        return Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE);
    }
}

3.6. Menambahkan bidang

Kami tidak dapat menambahkan kolom instance ke rekaman. Namun, kita dapat menambahkan kolom statis.
public record Contact(String name, String email) {
    private static final Pattern EMAIL_REGEX_PATTERN = Pattern
            .compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE);

    static Pattern emailRegex() {
        return EMAIL_REGEX_PATTERN;
    }
}
Perhatikan bahwa tidak ada batasan implisit dalam bidang statis. Jika perlu, dokumen tersebut mungkin tersedia untuk umum dan belum bersifat final.

Kesimpulan

Catatan adalah cara terbaik untuk menentukan kelas data. Mereka jauh lebih nyaman dan kuat dibandingkan pendekatan JavaBeans/POJO. Karena mudah diterapkan, cara ini sebaiknya dipilih dibandingkan cara lain dalam menciptakan objek nilai.
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION