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.
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.
- menjadikan medan peribadi dan muktamad .
- 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:-
Nama dan medan e-mel adalah peribadi dan muktamad secara lalai.
-
Kod mentakrifkan "pembina kanonik" yang mengambil medan sebagai parameter.
-
Medan boleh diakses melalui kaedah seperti getter - name() dan email() . Tiada penetap untuk medan, jadi data dalam objek menjadi tidak berubah.
-
Melaksanakan kaedah toString untuk mencetak medan seperti yang kami lakukan untuk kelas Kenalan .
-
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.
GO TO FULL VERSION