المنشئات المختصرة والتحقق
أضف منطق التحقق داخل المنشئات المختصرة لضمان سلامة البيانات
المنشئات المختصرة والتحقق درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.
المنشئات المختصرة
يُنفَّذ المنشئ المختصر في السجل قبل إسناد المكوّنات. ويتيح التحقق من البيانات أو تطبيعها دون تكرار عمليات إسناد المكوّنات.
المنشئ القياسي مقارنةً بالمنشئ المختصر
يسند المنشئ الأساسي القياسي المكوّنات صراحةً. أما المنشئ المختصر فيحذف قائمة المعاملات وعمليات الإسناد، إذ تحدث هذه العمليات تلقائيًا بعد تنفيذ جسم المنشئ.
// Standard canonical constructor
record Range(int min, int max) {
Range(int min, int max) {
if (min > max) throw new IllegalArgumentException("min > max");
this.min = min; // explicit assignment
this.max = max;
}
}
// Compact constructor (same behavior, less code)
record Range2(int min, int max) {
Range2 { // no parameter list, no assignments
if (min > max) throw new IllegalArgumentException("min > max");
// components are assigned automatically after this block
}
}التحقق في المنشئات المختصرة
تُعد المنشئات المختصرة الطريقة القياسية للتحقق من بيانات السجلات. ألقوا الاستثناءات مبكرًا لفرض الثوابت المنطقية.
record Email(String address) {
Email {
if (address == null || address.isBlank())
throw new IllegalArgumentException("Email cannot be blank");
if (!address.contains("@"))
throw new IllegalArgumentException("Invalid email: " + address);
address = address.toLowerCase().strip(); // normalize (Java 16+)
}
}
Email e = new Email(" Alice@Example.com ");
System.out.println(e.address()); // alice@example.com
try { new Email("not-an-email"); }
catch (IllegalArgumentException ex) { System.out.println(ex.getMessage()); }التطبيع في المنشئات المختصرة
يمكن تعديل متغيرات المكوّنات داخل المنشئ المختصر قبل إسنادها. ويؤدي ذلك إلى تطبيع البيانات عند الإنشاء.
record PersonName(String firstName, String lastName) {
PersonName {
firstName = capitalize(firstName);
lastName = capitalize(lastName);
}
private static String capitalize(String s) {
if (s == null || s.isEmpty()) return s;
return Character.toUpperCase(s.charAt(0)) +
s.substring(1).toLowerCase();
}
public String fullName() { return firstName + " " + lastName; }
}
PersonName name = new PersonName("jOHN", "DOE");
System.out.println(name.fullName()); // John Doeالنسخ الوقائي
بالنسبة إلى المكوّنات القابلة للتغيير، مثل المصفوفات أو المجموعات، أجروا نسخة وقائية في المنشئ المختصر للحفاظ على عدم قابلية التغيير.
import java.util.*;
record Snapshot(List<String> items) {
Snapshot {
items = List.copyOf(items); // defensive copy — unmodifiable
}
}
List<String> mutable = new ArrayList<>(List.of("a", "b", "c"));
Snapshot snap = new Snapshot(mutable);
mutable.add("d"); // doesn't affect snapshot
System.out.println(snap.items()); // [a, b, c]
try {
snap.items().add("e"); // UnsupportedOperationException
} catch (UnsupportedOperationException e) {
System.out.println("Snapshot is truly immutable!");
}سجل Range بحدود
سجل Range عملي يضمن أن تكون قيمة min أصغر من أو مساوية لقيمة max، ويوفّر دوال مساعدة مفيدة.
record Range(int min, int max) {
Range {
if (min > max) throw new IllegalArgumentException(
"min (" + min + ") must be <= max (" + max + ")");
}
public boolean contains(int value) { return value >= min && value <= max; }
public int size() { return max - min; }
public int clamp(int value) { return Math.max(min, Math.min(max, value)); }
}
Range valid = new Range(1, 10);
System.out.println(valid.contains(5)); // true
System.out.println(valid.clamp(15)); // 10
System.out.println(valid.size()); // 9تسلسل منطق المنشئ المختصر
للتحقق المعقد، استخرجوا دوالًا مساعدة واستدعواها من المنشئ المختصر.
record CreditCard(String number, String cvv, int expiryMonth, int expiryYear) {
CreditCard {
validateNumber(number);
validateCvv(cvv);
validateExpiry(expiryMonth, expiryYear);
number = number.replaceAll("[^0-9]", ""); // strip spaces/dashes
}
private static void validateNumber(String n) {
String digits = n.replaceAll("[^0-9]", "");
if (digits.length() < 13 || digits.length() > 19)
throw new IllegalArgumentException("Invalid card number length");
}
private static void validateCvv(String cvv) {
if (!cvv.matches("[0-9]{3,4}"))
throw new IllegalArgumentException("Invalid CVV");
}
private static void validateExpiry(int m, int y) {
if (m < 1 || m > 12) throw new IllegalArgumentException("Invalid month");
if (y < 2024) throw new IllegalArgumentException("Card expired");
}
}أنماط متعددة للمنشئات المختصرة
أنماط التحقق الشائعة المستخدمة في المنشئات المختصرة.
record Percentage(double value) {
Percentage {
if (value < 0 || value > 100)
throw new IllegalArgumentException(
"Percentage must be 0-100, got: " + value);
value = Math.round(value * 100.0) / 100.0; // round to 2 dp
}
public double asFraction() { return value / 100.0; }
}
Percentage tax = new Percentage(8.756);
System.out.println(tax.value()); // 8.76
System.out.println(tax.asFraction()); // 0.0876المنشئات غير الأساسية
يمكن أن تحتوي السجلات على منشئات إضافية، لكن يجب أن تفوّض إلى المنشئ الأساسي باستخدام this(...).
record Point(double x, double y) {
// Non-canonical constructor: origin point
Point() { this(0.0, 0.0); }
// Non-canonical: polar coordinates
static Point fromPolar(double r, double theta) {
return new Point(r * Math.cos(theta), r * Math.sin(theta));
}
public double distance(Point other) {
double dx = this.x - other.x;
double dy = this.y - other.y;
return Math.sqrt(dx*dx + dy*dy);
}
}
Point origin = new Point();
Point p = Point.fromPolar(5, Math.PI/4);
System.out.printf("Distance: %.2f%n", origin.distance(p)); // 5.00سجل مجموعة غير قابلة للتغيير
سجل يحتفظ بلقطة غير قابلة للتغيير من تفضيلات المستخدم، ويتحقق من البيانات ويطبّعها عند الإنشاء.
import java.util.*;
record UserPreferences(String theme, Set<String> enabledFeatures, int fontSize) {
private static final Set<String> VALID_THEMES = Set.of("light", "dark", "system");
private static final Set<String> VALID_FEATURES = Set.of("ai", "beta", "analytics");
UserPreferences {
if (!VALID_THEMES.contains(theme))
throw new IllegalArgumentException("Unknown theme: " + theme);
if (!VALID_FEATURES.containsAll(enabledFeatures))
throw new IllegalArgumentException("Unknown feature in: " + enabledFeatures);
if (fontSize < 10 || fontSize > 24)
throw new IllegalArgumentException("fontSize must be 10-24");
enabledFeatures = Set.copyOf(enabledFeatures); // defensive copy
}
}قيود المنشئات المختصرة
الأمور التي لا يمكن تنفيذها في المنشئ المختصر:
- لا يمكن إسناد المكوّنات صراحةً، إذ تُسند تلقائيًا بعد تنفيذ الكتلة
- لا يمكن استدعاء
this()أوsuper() - يؤدي إلقاء استثناء إلى منع إسناد جميع المكوّنات
record Safe(int value) {
Safe {
// CAN: validate and modify component variables
if (value < 0) value = 0; // normalized to 0 if negative
// value = this.value; // NOT NEEDED — assignment happens after block
}
}
System.out.println(new Safe(-5).value()); // 0 (normalized)
System.out.println(new Safe(10).value()); // 10اختبار سريع
في المنشئ المختصر، ماذا يحدث للتعديلات التي تُجرى على متغيرات المكوّنات؟
مراجعة: المنشئات المختصرة والتحقق
أهم النقاط:
- تُنفَّذ المنشئات المختصرة قبل إسناد المكوّنات، ولا حاجة إلى عمليات إسناد صريحة
- استخدموها للتحقق من المكوّنات أو تطبيعها أو إنشاء نسخ وقائية منها
- عدّلوا متغيرات المكوّنات لتطبيع القيم، مثل تحويلها إلى أحرف صغيرة أو إزالة المسافات أو نسخها
- ألقوا IllegalArgumentException للبيانات غير الصالحة لفرض الثوابت المنطقية
- استخدموا List.copyOf / Set.copyOf مع مكوّنات المجموعات القابلة للتغيير
- يجب أن تفوّض المنشئات غير الأساسية إلى المنشئ الأساسي باستخدام this(...)
الأسئلة الشائعة
هل درس «المنشئات المختصرة والتحقق» مجاني؟
نعم — نص درس «المنشئات المختصرة والتحقق» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.
ماذا ستتعلم في «المنشئات المختصرة والتحقق»؟
أضف منطق التحقق داخل المنشئات المختصرة لضمان سلامة البيانات تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟
لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «المنشئات المختصرة والتحقق»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟
نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- مقدمة إلى السجلّات
- المنشئات المختصرة والتحقق
- الأساليب المخصصة في السجلّات
- السجلّات مقابل الفئات وLombok