الحقول transient وserialVersionUID
استبعد الحقول الحساسة باستخدام transient، وحافظ على توافق الإصدارات باستخدام serialVersionUID
الحقول transient وserialVersionUID درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.
لماذا transient؟
ينبغي عدم حفظ بعض الحقول، مثل كلمات المرور ومقابض الملفات المفتوحة والنتائج المحسوبة مؤقتًا. علّموا هذه الحقول بـ transient، وعندها سيُتخطّى تسلسلها.
public class Session implements Serializable {
private String username;
private transient String password; // NOT serialized
private transient Connection dbConn; // NOT serialized
}قيمة الحقل transient بعد إلغاء التسلسل
بعد إلغاء التسلسل، تحصل حقول transient على قيم Java الافتراضية: null للكائنات، و0 للأعداد، وfalse للقيم المنطقية.
Session s = (Session) ois.readObject();
System.out.println(s.username); // "alice"
System.out.println(s.password); // null (transient)ما هو serialVersionUID؟
يمثّل serialVersionUID ثابتًا من النوع long يعمل كختم للإصدار. إذا تغيّرت الفئة ولم تتطابق قيمة UID مع القيمة الموجودة في الملف، فسيطرح إلغاء التسلسل InvalidClassException.
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
}قيمة UID المُنشأة تلقائيًا مقابل المصرّح بها صراحةً
إذا أغفلتم serialVersionUID، تُنشئ Java قيمةً له اعتمادًا على بنية الفئة. ويؤدي أي تغيير في حقل إلى تغيير UID بصمت، مما يكسر البيانات القديمة. صرّحوا به دائمًا بشكل صريح.
import java.io.ObjectStreamClass;
long uid = ObjectStreamClass.lookup(User.class).getSerialVersionUID();
System.out.println(uid); // e.g. 3526749255685047947InvalidClassException عند عدم تطابق الإصدارات
عند قراءة بيانات مُسلسَلة قديمة باستخدام فئة تغيّرت قيمة UID الخاصة بها، تطرح Java الاستثناء InvalidClassException: local class incompatible: stream classdesc serialVersionUID = X, local class serialVersionUID = Y.
تطوير الفئة بأمان
يمكنكم إضافة حقول جديدة إلى فئة قابلة للتسلسل بأمان من دون تغيير UID. وستُلغى أسلمة الدفقات القديمة مع تعيين القيمة الافتراضية للحقل الجديد. أما حذف الحقول أو إعادة تسميتها فأكثر خطورة.
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private String email; // Added in v2 — safe if UID unchanged
}transient مع التهيئة الكسولة
من الأنماط الشائعة تعليم حقل مخزّن مؤقتًا أو مشتق بـ transient، ثم إعادة حسابه عند الحاجة بعد إلغاء التسلسل باستخدام readResolve أو داخل دالة getter.
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
private String content;
private transient int wordCount = -1;
public int getWordCount() {
if (wordCount == -1) wordCount = content.split("\\s+").length;
return wordCount;
}
}لا تُسلسَل الحقول static مطلقًا
تنتمي الحقول static إلى الفئة لا إلى النسخة. ولا تُدرج مطلقًا في الدفق المُسلسَل؛ فالحقول التي تُسلسَل هي حقول النسخة فقط.
public class Counter implements Serializable {
private static final long serialVersionUID = 1L;
private static int instanceCount = 0; // NOT serialized
private int value;
}استخدام أداة serialver
تطبع أداة JDK المسماة serialver قيمة serialVersionUID الافتراضية لفئة ما: serialver com.example.User. استخدموها للحصول على القيمة قبل إضافتها بشكل صريح.
Externalizable كبديل
توسّع Externalizable الواجهة Serializable، وتمنحكم تحكمًا كاملًا عبر writeExternal وreadExternal، وهي مفيدة عندما تريدون التحكم صراحةً في الحقول من دون استخدام transient.
public class Config implements Externalizable {
private String host;
private transient String secret;
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(host);
}
public void readExternal(ObjectInput in) throws IOException {
host = in.readUTF();
}
}أفضل الممارسات
صرّحوا دائمًا بـ serialVersionUID. علّموا كلمات المرور والمقابض والبيانات المخزّنة مؤقتًا بـ transient. زيدوا قيمة UID عند إجراء تغييرات غير متوافقة، ووثّقوا سجل الإصدارات.
اختبار سريع
ما القيمة التي يحملها حقل int من نوع transient بعد إلغاء التسلسل؟
مراجعة
استخدموا transient لاستبعاد الحقول من التسلسل. وصرّحوا دائمًا بـ serialVersionUID للتحكم في الإصدارات. أما الحقول static فلا تُسلسَل مطلقًا مهما كان السبب.
الأسئلة الشائعة
هل درس «الحقول transient وserialVersionUID» مجاني؟
نعم — نص درس «الحقول transient وserialVersionUID» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.
ماذا ستتعلم في «الحقول transient وserialVersionUID»؟
استبعد الحقول الحساسة باستخدام transient، وحافظ على توافق الإصدارات باستخدام serialVersionUID تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟
لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «الحقول transient وserialVersionUID»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟
نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- أساسيات تسلسل Java
- الحقول transient وserialVersionUID
- التسلسل المخصص: writeObject وreadObject
- البدائل الحديثة: JSON وProtocol Buffers