مقدمة إلى السجلّات
صرّح بالسجلّات بوصفها حاويات بيانات موجزة وغير قابلة للتغيير، وافهم الأعضاء المُنشأة تلقائيًا لها
مقدمة إلى السجلّات درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.
مقدمة عن السجلات
سجلات Java، المتاحة منذ Java 16، طريقة موجزة لتعريف فئات حاملة للبيانات غير قابلة للتغيير. وهي تنشئ تلقائيًا الشيفرة النمطية، بما في ذلك المنشئ ودوال الوصول وequals وhashCode وtoString.
تعريف سجل
استخدموا الكلمة المفتاحية record متبوعة باسم السجل وقائمة المكوّنات. يصبح كل مكوّن حقلًا خاصًا ونهائيًا، بالإضافة إلى دالة وصول عامة.
record Point(double x, double y) {}
Point p = new Point(3.0, 4.0);
System.out.println(p.x()); // 3.0 (accessor, not getX())
System.out.println(p.y()); // 4.0
System.out.println(p); // Point[x=3.0, y=4.0]
System.out.println(p.equals(new Point(3.0, 4.0))); // trueالأعضاء المُنشأة تلقائيًا
ينشئ المصرّف تلقائيًا لكل سجل: المنشئ الأساسي، ودوال الوصول العامة، وequals() وhashCode() وtoString(). ولا حاجة إلى كتابة هذه العناصر يدويًا.
record Product(String name, double price, int stock) {}
Product p1 = new Product("Widget", 9.99, 100);
Product p2 = new Product("Widget", 9.99, 100);
System.out.println(p1.name()); // Widget
System.out.println(p1.price()); // 9.99
System.out.println(p1.equals(p2)); // true (structural)
System.out.println(p1.hashCode() == p2.hashCode()); // true
System.out.println(p1); // Product[name=Widget, price=9.99, stock=100]السجلات غير قابلة للتغيير
تكون مكوّنات السجل final. ولا يمكن تعديلها بعد الإنشاء، ولذلك تمثّل السجلات كائنات قيم غير قابلة للتغيير.
record Money(long cents, String currency) {}
Money price = new Money(999, "USD");
// price.cents = 500; // Compile error — final field!
// To "update" a record, create a new one
Money discounted = new Money(price.cents() - 100, price.currency());
System.out.println(discounted); // Money[cents=899, currency=USD]السجلات تمتد إلى Object فقط
تمتد السجلات ضمنيًا إلى java.lang.Record، ولا يمكنها الامتداد إلى فئات أخرى. لكنها تستطيع تطبيق الواجهات.
interface Describable { String describe(); }
record Circle(double radius) implements Describable {
public String describe() {
return String.format("Circle with radius %.1f", radius);
}
public double area() {
return Math.PI * radius * radius;
}
}
Circle c = new Circle(5.0);
System.out.println(c.describe()); // Circle with radius 5.0
System.out.printf("Area: %.2f%n", c.area()); // Area: 78.54السجلات ضمن المجموعات
بما أن السجلات تطبّق equals وhashCode بشكل صحيح استنادًا إلى جميع المكوّنات، فإنها تعمل كما ينبغي كمفاتيح في Map وعناصر في Set.
import java.util.*;
record Coordinate(int row, int col) {}
Map<Coordinate, String> grid = new HashMap<>();
grid.put(new Coordinate(0, 0), "Origin");
grid.put(new Coordinate(1, 2), "Target");
// Lookup with equal-valued record works correctly
System.out.println(grid.get(new Coordinate(0, 0))); // Origin
System.out.println(grid.get(new Coordinate(1, 2))); // Target
Set<Coordinate> visited = new HashSet<>();
visited.add(new Coordinate(3, 3));
System.out.println(visited.contains(new Coordinate(3, 3))); // trueالسجلات بوصفها DTOs
تُعد السجلات مثالية لكائنات نقل البيانات (DTOs) في REST APIs، إذ تنقل البيانات بين الطبقات دون سلوك.
record CreateUserRequest(String email, String displayName, String plan) {}
record UserResponse(long id, String email, String displayName,
String plan, String createdAt) {}
// Simulating a service call
static UserResponse createUser(CreateUserRequest req) {
long id = 42L;
return new UserResponse(id, req.email(), req.displayName(),
req.plan(), java.time.Instant.now().toString());
}
CreateUserRequest req = new CreateUserRequest("alice@example.com", "Alice", "PRO");
UserResponse resp = createUser(req);
System.out.println(resp);تفكيك السجلات
تتوافق السجلات جيدًا مع مطابقة الأنماط. ويمكن تفكيكها في تعبيرات switch في Java 21 وما بعده.
sealed interface Shape permits Circle, Rectangle, Triangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}
record Triangle(double base, double height) implements Shape {}
static double area(Shape s) {
return switch (s) {
case Circle(double r) -> Math.PI * r * r;
case Rectangle(double w, double h) -> w * h;
case Triangle(double b, double h) -> 0.5 * b * h;
};
}
System.out.printf("%.2f%n", area(new Circle(5))); // 78.54
System.out.printf("%.2f%n", area(new Rectangle(4, 6))); // 24.00تسلسل السجلات
تطبّق السجلات Serializable تلقائيًا عند التصريح بذلك. كما تعمل مباشرةً بشكل جيد مع مكتبات JSON مثل Jackson وGson.
// With Jackson (add @JsonProperty if needed)
import com.fasterxml.jackson.databind.ObjectMapper;
record OrderSummary(String orderId, double total, String status) {}
ObjectMapper mapper = new ObjectMapper();
OrderSummary order = new OrderSummary("ORD-001", 149.99, "SHIPPED");
String json = mapper.writeValueAsString(order);
System.out.println(json);
// {"orderId":"ORD-001","total":149.99,"status":"SHIPPED"}
OrderSummary restored = mapper.readValue(json, OrderSummary.class);
System.out.println(order.equals(restored)); // trueالسجلات المتداخلة
يمكن أن تحتوي السجلات على سجلات أخرى بوصفها مكوّنات، ما يتيح بناء رسوم بيانية غنية من الكائنات غير القابلة للتغيير.
record Address(String street, String city, String country) {}
record Customer(long id, String name, Address address) {}
Address addr = new Address("123 Main St", "New York", "US");
Customer customer = new Customer(1L, "Alice", addr);
System.out.println(customer.name()); // Alice
System.out.println(customer.address().city()); // New York
System.out.println(customer); // Customer[id=1, name=Alice, address=Address[street=123 Main St, city=New York, country=US]]قيود السجلات
توجد بعض القيود التي ينبغي الانتباه إليها في السجلات:
- لا يمكنها الامتداد إلى فئات أخرى، إذ تمتد ضمنيًا إلى Record
- تكون المكوّنات دائمًا نهائية، لذلك لا توجد حالة قابلة للتغيير
- لا يمكن التصريح بحقول مثيلات خارج قائمة المكوّنات
- لا يمكن أن تكون مجردة
// Records CAN have static fields and methods
record Temperature(double celsius) {
static final double ABSOLUTE_ZERO = -273.15;
public double toFahrenheit() {
return celsius * 9.0/5.0 + 32;
}
public static Temperature fromFahrenheit(double f) {
return new Temperature((f - 32) * 5.0/9.0);
}
}
System.out.println(Temperature.fromFahrenheit(98.6)); // Temperature[celsius=37.0]اختبار سريع
ما الأعضاء التي ينشئها مُصرّف Java تلقائيًا للسجل؟
مراجعة: مقدمة عن السجلات
أهم النقاط:
- تعرّف السجلات حوامل بيانات غير قابلة للتغيير مع قدر ضئيل من الشيفرة النمطية
- العناصر المُنشأة تلقائيًا: المنشئ الأساسي ودوال الوصول وequals وhashCode وtoString
- المكوّنات نهائية، فالسجلات غير قابلة للتغيير حسب التصميم
- يمكن للسجلات تطبيق الواجهات، لكنها لا تستطيع الامتداد إلى الفئات
- تُعد مثالية لـ DTOs وكائنات القيمة واستجابات API
- تعمل بشكل صحيح كمفاتيح HashMap وعناصر HashSet بفضل المساواة البنيوية
الأسئلة الشائعة
هل درس «مقدمة إلى السجلّات» مجاني؟
نعم — نص درس «مقدمة إلى السجلّات» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.
ماذا ستتعلم في «مقدمة إلى السجلّات»؟
صرّح بالسجلّات بوصفها حاويات بيانات موجزة وغير قابلة للتغيير، وافهم الأعضاء المُنشأة تلقائيًا لها تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟
لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «مقدمة إلى السجلّات»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟
نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- مقدمة إلى السجلّات
- المنشئات المختصرة والتحقق
- الأساليب المخصصة في السجلّات
- السجلّات مقابل الفئات وLombok