سؤال

في Java، لا يتم إجراء تسلسل للحقول الثابتة والعابرة.ومع ذلك، اكتشفت أن تهيئة الحقول الثابتة تؤدي إلى تغيير serialVersionUID الذي تم إنشاؤه.على سبيل المثال، static int MYINT = 3; يؤدي إلى تغيير serialVersionUID.في هذا المثال، يكون الأمر منطقيًا لأن الإصدارات المختلفة من الفصل ستحصل على قيم أولية مختلفة.لماذا تؤدي أي عملية تهيئة إلى تغيير serialVersionUID؟على سبيل المثال، static String MYSTRING = System.getProperty("foo"); يؤدي أيضًا إلى تغيير serialVersionUID.

على وجه التحديد، سؤالي هو لماذا تؤدي التهيئة باستخدام إحدى الطرق إلى تغيير serialVersionUID.المشكلة التي واجهتها هي أنني أضفت حقلاً ثابتًا جديدًا تمت تهيئته بقيمة خاصية النظام (getProperty).تسبب هذا التغيير في حدوث استثناء في التسلسل في مكالمة بعيدة.

هل كانت مفيدة؟

المحلول

يمكنك العثور على بعض المعلومات حول ذلك في علة 4365406 وفي خوارزمية للحوسبة serialVersionUID.بشكل أساسي، عند تغيير تهيئة ملفك static عضو مع System.getProperty(), ، يقدم المترجم ملفًا جديدًا static الممتلكات في صفك الرجوع إلى System فئة (أفترض أن System لم تتم الإشارة إلى الفئة من قبل في صفك)، وبما أن هذه الخاصية التي قدمها المترجم ليست خاصة، فإنها تشارك في serialVersionUID حساب.

الأخلاق:استخدم دائمًا صريحًا serialVersionUID, ، ستوفر بعض دورات وحدة المعالجة المركزية وبعض المشاكل :)

نصائح أخرى

يتم حساب serialVersionUID التلقائي بناءً على أعضاء الفصل.يمكن عرضها لملف فئة باستخدام أداة javap في Sun JDK.

في الحالة المذكورة في السؤال، العضو الذي تمت إضافته/إزالته هو المُهيئ الثابت.يظهر هذا كـ ()V في ملفات الفئة.يمكن تفكيك محتويات الطريقة باستخدام javap -c.يجب أن تكون قادرًا على إجراء استدعاء System.getProperty("foo") وتعيينه إلى MYSTRING.ومع ذلك، يتم دعم التعيين الذي يحتوي على سلسلة حرفية (أو أي ثابت في وقت الترجمة كما هو محدد في مواصفات لغة Java) مباشرة بواسطة ملف الفئة، وبالتالي إزالة الحاجة إلى مُهيئ ثابت.

من الحالات الشائعة لاستهداف التعليمات البرمجية J2SE 1.4 (استخدم -source 1.4 -target 1.4) أو ما قبله هي الحقول الثابتة لمثيلات Class القديمة التي تظهر كحرفية للفئة في التعليمات البرمجية المصدر (MyClass.class).يتم البحث عن مثيل الفئة عند الطلب باستخدام Class.forName، ويتم تخزينه في حقل ثابت.هذا الحقل الثابت هو الذي يعطل serialVersionUID.بدءًا من الإصدار J2SE 5.0، يوفر أحد أشكال كود التشغيل ldc دعمًا مباشرًا للقيم الحرفية للفئة، مما يلغي الحاجة إلى المجال الاصطناعي.مرة أخرى، كل هذا يمكن إظهاره باستخدام javap -c.

إذا قرأت المواصفات بشكل صحيح التلقائي serialVersionUID لا ينبغي أن يتغير إذا قمت بتغيير قيمة الحقل الثابت العابر.نلقي نظرة على الفصل 5.6 من المواصفات.

لكن, ، إذا فكرت في هذا قليلاً - فستبدأ بإجراء تسلسل لكائن يحتوي على static int MYINT = 3, ، عندما تقوم بعد ذلك بإلغاء تسلسل الفئة، فإنك تتوقع استعادة نفس الكائن مرة أخرى، أي باستخدام MYINT = 3.لذا، إذا قمت بتغيير التهيئة الثابتة، فإنك تتوقع حدوث serialVersionUID للتغيير لأنه لا يمكنك استعادة نفس الكائن مرة أخرى.

على أي حال, ، احتفظ بهذا في جميع فئاتك القابلة للتسلسل ويمكنك التحكم في serialVersionUID:

private static final long serialVersionUID = 7526472295622776147L;

لقد قمت بتحديث السؤال ليكون أكثر وضوحا.أفهم سبب تغيير التهيئة باستخدام حرفي serialVersionUID ولكن ليس سبب تغيير التهيئة الديناميكية له.إذا قمت بالتهيئة باستخدام طريقة ما، فقد تكون القيمة مختلفة دائمًا.

وضع serialVersionUID بشكل صريح، لا بأس في إصدار لاحق من الفصل الدراسي إلا إذا كنت متأكدًا من أنه تغيير آمن.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top