JavaRush /Blog Java /Random-MS /Coffee break #128. Panduan Rekod Java

Coffee break #128. Panduan Rekod Java

Diterbitkan dalam kumpulan
Sumber: abhinavpandey.dev Dalam tutorial ini, kami akan merangkumi asas penggunaan Rekod dalam Java. Rekod telah diperkenalkan di Java 14 sebagai cara untuk mengalih keluar kod boilerplate di sekitar penciptaan objek Nilai sambil mengambil kesempatan daripada objek tidak berubah. Coffee break #128.  Panduan Rekod Java - 1

1. Konsep asas

Sebelum kita masuk ke dalam entri itu sendiri, mari kita lihat masalah yang mereka selesaikan. Untuk melakukan ini, kita perlu ingat bagaimana objek nilai dicipta sebelum Java 14.

1.1. Objek nilai

Objek nilai adalah sebahagian daripada aplikasi Java. Mereka menyimpan data yang perlu dipindahkan antara lapisan aplikasi. Objek nilai mengandungi medan, pembina dan kaedah untuk mengakses medan tersebut. Di bawah ialah 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. Kesamaan antara objek Nilai

Objek nilai juga boleh menyediakan cara untuk membandingkannya untuk kesaksamaan. Secara lalai, Java membandingkan kesamaan objek dengan membandingkan alamat memori mereka. Walau bagaimanapun, dalam beberapa kes, objek yang mengandungi data yang sama mungkin dianggap sama. Untuk melaksanakan ini, kita boleh mengatasi kaedah equals dan .hashCode . Mari kita laksanakannya untuk kelas Kenalan :

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. Ketidakbolehubahan objek Nilai

Objek nilai mestilah tidak boleh diubah. Ini bermakna kita mesti mengehadkan cara kita boleh menukar medan sesuatu objek. Ini adalah dinasihatkan atas sebab-sebab berikut:
  • Untuk mengelakkan risiko menukar nilai medan secara tidak sengaja.
  • Untuk memastikan objek yang sama kekal sama sepanjang hayat mereka.
Oleh kerana kelas Kenalan sudah tidak boleh diubah, kami kini:
  1. menjadikan medan peribadi dan muktamad .
  2. hanya disediakan getter untuk setiap medan (tiada setter ).

1.4. Mendaftarkan objek Nilai

Selalunya kita perlu mendaftarkan nilai yang terkandung dalam objek. Ini dilakukan dengan menyediakan kaedah toString . Setiap kali objek didaftarkan atau dicetak, kaedah toString dipanggil . Cara paling mudah di sini ialah mencetak nilai setiap medan. Berikut ialah contoh:

public class Contact {
    // ...
    @Override
    public String toString() {
        return "Contact[" +
                "name='" + name + '\'' +
                ", email=" + email +
                ']';
    }
}

2. Kurangkan templat dengan Rekod

Memandangkan kebanyakan objek nilai mempunyai keperluan dan fungsi yang sama, adalah baik untuk memudahkan proses menciptanya. Mari lihat bagaimana rakaman membantu mencapai perkara ini.

2.1. Menukar kelas Orang kepada Rekod

Mari buat entri kelas Kenalan yang mempunyai fungsi yang sama seperti kelas Kenalan yang ditakrifkan di atas.

public record Contact(String name, String email) {}
Kata kunci rekod digunakan untuk mencipta kelas Rekod . Rekod boleh diproses oleh pemanggil dengan cara yang sama seperti kelas. Contohnya, untuk membuat contoh entri baharu, kita boleh menggunakan kata kunci baharu .

Contact contact = new Contact("John Doe", "johnrocks@gmail.com");

2.2. Gelagat Lalai

Kami telah mengurangkan kod kepada satu baris. Mari senaraikan apa yang termasuk:
  1. Nama dan medan e-mel adalah peribadi dan muktamad secara lalai.

  2. Kod mentakrifkan "pembina kanonik" yang mengambil medan sebagai parameter.

  3. Medan boleh diakses melalui kaedah seperti getter - name() dan email() . Tiada penetap untuk medan, jadi data dalam objek menjadi tidak berubah.

  4. Melaksanakan kaedah toString untuk mencetak medan seperti yang kami lakukan untuk kelas Kenalan .

  5. Kaedah sama dan .hashCode yang dilaksanakan . Ia termasuk semua medan, sama seperti kelas Kenalan .

2.3 Pembina kanonik

Pembina lalai mengambil semua medan sebagai parameter input dan menetapkannya kepada medan. Sebagai contoh, Pembina Canonical lalai ditunjukkan di bawah:

public Contact(String name, String email) {
    this.name = name;
    this.email = email;
}
Jika kita mentakrifkan pembina dengan tandatangan yang sama dalam kelas rakaman, ia akan digunakan dan bukannya pembina kanonik.

3. Bekerja dengan rekod

Kita boleh mengubah tingkah laku entri dalam beberapa cara. Mari lihat beberapa kes penggunaan dan cara mencapainya.

3.1. Mengatasi pelaksanaan lalai

Sebarang pelaksanaan lalai boleh diubah dengan mengatasinya. Contohnya, jika kita ingin menukar kelakuan kaedah toString , maka kita boleh mengatasinya antara pendakap kerinting {} .

public record Contact(String name, String email) {
    @Override
    public String toString() {
        return "Contact[" +
                "name is '" + name + '\'' +
                ", email is" + email +
                ']';
    }
}
Begitu juga, kita boleh mengatasi kaedah equals dan hashCode .

3.2. Kit pembinaan padat

Kadang-kadang kita mahu pembina melakukan lebih daripada sekadar memulakan medan. Untuk melakukan ini, kami boleh menambah operasi yang diperlukan pada entri kami dalam Compact Constructor. Ia dipanggil padat kerana ia tidak perlu menentukan permulaan medan atau senarai parameter.

public record Contact(String name, String email) {
    public Contact {
        if(!email.contains("@")) {
            throw new IllegalArgumentException("Invalid email");
        }
    }
}
Ambil perhatian bahawa tiada senarai parameter, dan permulaan nama dan e-mel berlaku di latar belakang sebelum semakan dilakukan.

3.3. Menambah Pembina

Anda boleh menambah berbilang pembina pada rekod. Mari kita lihat beberapa contoh dan batasan. Mula-mula, mari tambah pembina sah baharu:

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 kes pertama, pembina lalai diakses menggunakan kata kunci ini . Pembina kedua mengatasi pembina lalai kerana ia mempunyai senarai parameter yang sama. Dalam kes ini, entri itu sendiri tidak akan mencipta pembina lalai. Terdapat beberapa sekatan ke atas pembina.

1. Pembina lalai hendaklah sentiasa dipanggil daripada mana-mana pembina lain.

Sebagai contoh, kod di bawah tidak akan disusun:

public record Contact(String name, String email) {
    public Contact(String name) {
        this.name = "John Doe";
        this.email = null;
    }
}
Peraturan ini memastikan bahawa medan sentiasa dimulakan. Ia juga dijamin bahawa operasi yang ditakrifkan dalam pembina padat sentiasa dilaksanakan.

2. Tidak mustahil untuk mengatasi pembina lalai jika pembina padat ditakrifkan.

Apabila pembina padat ditakrifkan, pembina lalai dicipta secara automatik dengan permulaan dan logik pembina padat. Dalam kes ini, pengkompil tidak akan membenarkan kami mentakrifkan pembina dengan hujah yang sama seperti pembina lalai. Sebagai contoh, dalam kod ini kompilasi tidak akan berlaku:

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. Melaksanakan Antara Muka

Seperti mana-mana kelas, kami boleh melaksanakan antara muka dalam rekod.

public record Contact(String name, String email) implements Comparable<Contact> {
    @Override
    public int compareTo(Contact o) {
        return name.compareTo(o.name);
    }
}
Nota PENTING. Untuk memastikan kebolehubah sepenuhnya, rekod tidak boleh diwarisi. Penyertaan adalah muktamad dan tidak boleh dikembangkan. Mereka juga tidak boleh melanjutkan kelas lain.

3.5. Menambah Kaedah

Sebagai tambahan kepada pembina, yang mengatasi kaedah dan pelaksanaan antara muka, kami juga boleh menambah sebarang kaedah yang kami mahu. Sebagai contoh:

public record Contact(String name, String email) {
    String printName() {
        return "My name is:" + this.name;
    }
}
Kami juga boleh menambah kaedah statik. Sebagai contoh, jika kita ingin mempunyai kaedah statik yang mengembalikan ungkapan biasa yang boleh kita semak e-mel, maka kita boleh mentakrifkannya seperti yang ditunjukkan di bawah:

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. Menambah medan

Kami tidak boleh menambah medan contoh pada rekod. Walau bagaimanapun, kita boleh menambah medan statik.

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;
    }
}
Ambil perhatian bahawa tiada sekatan tersirat dalam medan statik. Jika perlu, ia mungkin tersedia secara umum dan tidak muktamad.

Kesimpulan

Rekod ialah cara terbaik untuk menentukan kelas data. Mereka jauh lebih mudah dan berkuasa daripada pendekatan JavaBeans/POJO. Kerana ia mudah untuk dilaksanakan, ia harus diutamakan berbanding cara lain untuk mencipta objek nilai.
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION