تقدم Java 14 طريقة جديدة لإنشاء الفئات تسمى Records. في هذا البرنامج التعليمي، سنتعلم:
- لماذا نحتاج إلى Java Records
- كيفية إنشاء Records واستخدامها
- تجاوز وتوسيع فئات Records
القراءة الموصى بها: ميزات Java 14
لماذا نحتاج إلى Java Records؟
كانت إحدى الشكاوى الشائعة حول Java هي ضجيجها الزائد. إذا كنت بحاجة إلى إنشاء فئة POJO بسيطة، فإنه يتطلب الشيفرة الروتينية التالية.
- حقول خاصة
- طرق الحصول والتعيين (Getter وSetter)
- بناة (Constructors)
- طرق hashCode()، equals()، وtoString()
هذا الضجيج هو واحد من الأسباب وراء اهتمام كبير في Kotlin و Project Lombok.
في الواقع، كانت إحباطات كتابة هذه الطرق العامة في كل مرة تؤدي إلى الاختصارات لإنشائها في بيئات تطوير Java مثل Eclipse و IntelliJ IDEA.
فيما يلي لقطة شاشة تظهر خيار بيئة تطوير Eclipse لإنشاء الطرق الاحتفالية لفئة.

تهدف Java Records إلى إزالة هذا الضجيج عن طريق توفير هيكل مدمج لإنشاء فئات POJO.
كيفية إنشاء سجلات Java
سجلات Java هي ميزة معاينة تم تطويرها في إطار JEP 359. لذلك، تحتاج إلى شيئين لإنشاء سجلات في مشاريع Java الخاصة بك.
- يجب تثبيت JDK 14. إذا كنت تستخدم بيئة تطوير متكاملة، فيجب أن توفر دعمًا لـ Java 14 أيضًا. توفر Eclipse و IntelliJ بالفعل دعمًا لـ Java 14، لذا نحن بخير هنا.
- تمكين ميزة المعاينة: بشكل افتراضي، تكون ميزات المعاينة معطلة. يمكنك تمكينها في Eclipse من إعدادات مترجم Java للمشروع.

يمكنك تمكين ميزات معاينة Java 14 في سطر الأوامر باستخدام الخيار --enable-preview -source 14
.
لنفترض أنني أريد إنشاء فئة نموذج موظف. ستبدو بشكل ما مثل الشيفرة التالية.
package com.journaldev.java14;
import java.util.Map;
public class Employee {
private int id;
private String name;
private long salary;
private Map<String, String> addresses;
public Employee(int id, String name, long salary, Map<String, String> addresses) {
super();
this.id = id;
this.name = name;
this.salary = salary;
this.addresses = addresses;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public long getSalary() {
return salary;
}
public Map<String, String> getAddresses() {
return addresses;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((addresses == null) ? 0 : addresses.hashCode());
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + (int) (salary ^ (salary >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (addresses == null) {
if (other.addresses != null)
return false;
} else if (!addresses.equals(other.addresses))
return false;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (salary != other.salary)
return false;
return true;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + ", addresses=" + addresses + "]";
}
}
أوووه، هذا أكثر من 70 سطرًا من الشيفرة المولدة تلقائيًا. الآن دعونا نرى كيفية إنشاء فئة سجل موظف، التي توفر في الأساس نفس الميزات.
package com.journaldev.java14;
import java.util.Map;
public record EmpRecord(int id, String name, long salary, Map<String, String> addresses) {
}
واو، لا يمكن أن يكون أقصر من ذلك. أنا بالفعل أحب فئات السجلات.
الآن، دعونا نستخدم الأمر javap
لمعرفة ما يحدث خلف الكواليس عند ترجمة سجل.
# javac --enable-preview -source 14 EmpRecord.java
Note: EmpRecord.java uses preview language features.
Note: Recompile with -Xlint:preview for details.
# javap EmpRecord
Compiled from "EmpRecord.java"
public final class EmpRecord extends java.lang.Record {
public EmpRecord(int, java.lang.String, long, java.util.Map<java.lang.String, java.lang.String>);
public java.lang.String toString();
public final int hashCode();
public final boolean equals(java.lang.Object);
public int id();
public java.lang.String name();
public long salary();
public java.util.Map<java.lang.String, java.lang.String> addresses();
}
#

# javac —تمكين–معاينة –المصدر 14 EmpRecord.جافا
# javap EmpRecord
إذا كنت ترغب في المزيد من التفاصيل الداخلية، قم بتشغيل الأمر javap مع خيار -v.
- A Record class is final, so we can’t extend it.
- # javap -v EmpRecord
- نقاط مهمة حول فئات السجلات
- توسيع فئات السجلات بشكل ضمني
java.lang.Record
فئة. - A single constructor is created with all the fields specified in the record definition.
- جميع الحقول المحددة في إعلان السجل هي نهائية.
- حقول السجل غير قابلة للتغيير “سطحيًا” وتعتمد على النوع. على سبيل المثال، يمكننا تغيير حقل العناوين عن طريق الوصول إليه ومن ثم إجراء التحديثات عليه.
توفر فئة السجل تلقائيًا طرق وصول للحقول. اسم الطريقة هو نفس اسم الحقل، وليس مثل الطرق العامة والتقليدية للحصول على القيم.
توفر فئة السجل طرق تنفيذ hashCode()، equals()، و toString() أيضًا.
package com.journaldev.java14;
public class RecordTest {
public static void main(String[] args) {
EmpRecord empRecord1 = new EmpRecord(10, "Pankaj", 10000, null);
EmpRecord empRecord2 = new EmpRecord(10, "Pankaj", 10000, null);
استخدام السجلات في برنامج Java
System.out.println(empRecord1);
لنلق نظرة على مثال بسيط عن استخدام فئة EmpRecord لدينا.
System.out.println("Name: "+empRecord1.name());
System.out.println("ID: "+empRecord1.id());
// toString()
System.out.println(empRecord1.equals(empRecord2));
// الوصول إلى الحقول
System.out.println(empRecord1 == empRecord2);
}
}
// equals()
EmpRecord[id=10, name=Pankaj, salary=10000, addresses=null]
Name: Pankaj
ID: 10
true
false
// hashCode()
الإخراج:
يعمل كائن السجل بنفس الطريقة كأي فئة نموذجية، كائن بيانات، إلخ.
public record EmpRecord(int id, String name, long salary, Map<String, String> addresses) {
public EmpRecord {
if (id < 0)
throw new IllegalArgumentException("employee id can't be negative");
if (salary < 0)
throw new IllegalArgumentException("employee salary can't be negative");
}
}
EmpRecord empRecord1 = new EmpRecord(-10, "Pankaj", 10000, null);
أحيانًا، نرغب في إضافة بعض التحققات أو تسجيلات في البناء الخاص بنا. على سبيل المثال، لا ينبغي أن يكون معرف الموظف والراتب سالبين. البناء الافتراضي لن يحتوي على هذا التحقق. يمكننا إنشاء بناء مضغوط في فئة السجل. سيتم وضع كود هذا البناء في بداية البناء الذي تم إنشاؤه تلقائيًا.
Exception in thread "main" java.lang.IllegalArgumentException: employee id can't be negative
at com.journaldev.java14.EmpRecord.<init>(EmpRecord.java:9)
إذا قمنا بإنشاء EmpRecord مثل الكود التالي:
ستحدث استثناء تشغيلي عند تنفيذ:
public record EmpRecord(int id, String name, long salary, Map<String, String> addresses) {
public int getAddressCount() {
if (this.addresses != null)
return this.addresses().size();
else
return 0;
}
}
هل يمكن لفئات التسجيلات أن تحتوي على طرق؟
نعم، يمكننا إنشاء طريقة في التسجيلات.
ولكن، التسجيلات مخصصة لحمل البيانات. يجب تجنب وجود طرق فائدية في فئة التسجيل. على سبيل المثال، يمكن إنشاء الطريقة أعلاه في فئة فائدية.
إذا كنت تعتقد أن وجود طريقة ضروري لفئتك التسجيل، فكّر بعناية هل تحتاج حقًا إلى فئة تسجيل؟
Source:
https://www.digitalocean.com/community/tutorials/java-records-class