فهم هذا التحذير: الطبقة المتسلسلة لا تعلن عن SerialVersionuid نهائي ثابت

StackOverflow https://stackoverflow.com/questions/1514881

سؤال

لدي بعض التعليمات البرمجية الثابتة:

someMethodThatTakesAHashMap(new HashMap<K, V>() {
{
  put("a","value-a"); 
  put("c","value-c");}
});

لسبب ما أتلقى تحذيرا من الكسوف: فئة Serializable لا تعلن عن SerialVersionUID نهائي ثابت.

هل هذا يشكو من الطبقة المجهولة؟ ماذا يمكنني أن أفعل حيال ذلك، أو يجب أن أقمعها فقط.

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

المحلول

يستدعي بناء الجملة الذي تستخدمه تهيج مزدوج التهيئة - وهو في الواقع "مثيل تهيئة كتلة. هذا جزء من الفئة الداخلية المجهولة"(بالتأكيد ليس هاكا). لذلك، عند استخدام هذه التدوين، كنت في الواقع تحديد فئة جديدة (!).

"المشكلة" في قضيتك هي ذلك HashMap تنفذ Serializable. وبعد لا تحتوي هذه الواجهة على أي طرق و يقدم فقط لتحديد دلالات أن تكون متسلسلة. وبعد بمعنى آخر، إنها واجهة علامة وأنت لا تضطر إلى تطبيق أي شيء. ولكن, ، أثناء التحيز، يستخدم Java رقم إصدار يسمى serialVersionUID للتحقق من أن الإصدار المتسلسل متوافق مع الهدف. إذا كنت لا تقدم هذا serialVersionUID, ، سيتم حسابها. و، كما هو موثق في جافادوك Serializable, ، القيمة المحسوبة حساسة للغاية، وبالتالي فإن الموصى بها تعلن صراحة عن تجنب أي مشاكل لتحمل. وهذا ما هو الكسوف "يشكو" حول (لاحظ أن هذا مجرد تحذير).

لذلك، لتجنب هذا التحذير، يمكنك إضافة serialVersionUID إلى الطبقة الداخلية الكارهية:

someMethodThatTakesAHashMap(new HashMap<String, String>() {
    private static final long serialVersionUID = -1113582265865921787L;

    {
        put("a", "value-a");
        put("c", "value-c");
    }
});

لكنك تفقد وجزأة بناء الجملة (وقد لا تحتاجها حتى).

سيكون هناك خيار آخر هو تجاهل التحذير عن طريق إضافة @SuppressWarnings("serial") إلى الطريقة التي تتصل بها someMethodThatTakesAHashMap(Map). وبعد هذا يبدو أكثر ملاءمة في قضيتك.

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

لذلك، بينما أرغب في استخدامه في الاختبارات (للحصول على موجة)، أميل إلى تجنب استخدامه في رمز "منتظم".

نصائح أخرى

نعم، يمكنك قمع التحذير، لكنني أعد كتابة ذلك مثل هذا:

HashMap<String, String> map  = new HashMap<String, String>();
map.put("a","value-a"); 
map.put("c","value-c");
someMethodThatTakesAHashMap(map);

لا حاجة قمع، وأفضل بكثير القراءة، المنظمة البحرية الدولية.

أتفق عموما مع بارت ك.، ولكن لأغراض إعلامية:
يمكن أيضا إلغاء التحذير من خلال إضافة الحقل، والذي يمكن إنشاؤه تلقائيا عن طريق ضرب CTRL + 1.
يمكن أيضا قمع التحذير من خلال إضافة التعليق التوضيحي في SuppressWarnings ("التسلسل") قبل التعريف.
تنفذ الطبقة المجهولة المسلعة، ويتطلب Serializeable هذا الحقل الثابت حتى يمكن تمييز الإصدارات عند تسلسل وتسلسل. مزيد من المعلومات هنا:
http://www.javablogging.com/what-is-serialversionuid/

ال ImmutableMap فئة من مكتبة مجموعات Google مفيدة لهذا الموقف. على سبيل المثال

someMethodThatTakesAHashMap(ImmutableMap.<K, V>builder().put("a","value-a").put("c","value-c").build());

أو

someMethodThatTakesAHashMap(ImmutableMap.of("a","value-a","c","value-c"));

لمعالجة النصف الآخر من سؤالك، "هل يجب أن أقفه؟" -

نعم. في رأيي، هذا تحذير فظيع. serialversionuid ينبغي افتراضيا ليس أن تستخدم، وليس العكس.

إذا لم تقم بإضافة SerialVersionUID، فإن أسوأ شيء يحدث هو أن نسختين من الكائن المتوافق في الواقع تعتبر متوافقة غير متوافقة. SerialVersionuid هو وسيلة للإعلان عن عدم تغيير توافق التسلسل، وتجاوز التقييم الافتراضي لجافا.

باستخدام SerialVersionUID، أسوأ شيء يحدث هو أنك تفشل عن غير قصد في تحديث المعرف عند تغيير نموذج Serialized Class بطريقة غير متوافقة. في أحسن الأحوال، تحصل أيضا على خطأ في وقت التشغيل. في أسوأ الأحوال، يحدث شيء أسوأ. وتخيل مدى سهولة فشل في تحديثه.

كانت نيتك هي تهيئة مثيل مجهول Hashmap. التحذير هو فكرة أن رمزك يفعل أكثر مما كنت المقصود.

ما نبحث عنه هو وسيلة لتهيئة مثيل Hashmap مجهول. إن ما لدينا أعلاه يخلق فئة فرعية مجهولة من HASHMAP ثم يخلق مثال مجهول لهذه الفئة المجهولة.

لأن الكود لا يقصد به، كنت أسميها هاكا.

ما نريده حقا هو شيء مثل هذا:

foo(new HashMap<String, String>({"a", "value-a"}, {"c", "value-c"}));

لكن للأسف هذا ليس صحيحا جافا. لا توجد طريقة للقيام بأي شيء في طريقة آمنة من النوع باستخدام مجموعة من أزواج المفتاح / القيمة. جاوة بسيطة لا تملك القوة التعبيرية.

يتم إغلاق الطرق الثابتة لجهاز Google Collection. (انظر إجابة فينو.)

لذلك الحفاظ على الأشياء بسيطة. الذهاب مع حل بارت ك ما لم يكن الكود الخاص بك متأخرا بهذا التهيئة. إذا كان الأمر كذلك استخدام IMMUTABLEMAP. أو لفة فرعية Hashmap الخاصة بك مع "من أساليب المصنع". أو قم بإنشاء هذه الأسلوب "من أساليب" أسلوب "في فئة فائدة. إليك واحدة لاثنين من أزواج المفتاح / القيمة:

public final MapUtil {
    public static <K,V> Map<K,V> makeMap(K k1, V v1, K k2, V v2) {
        Map<K,V> m = new HashMap<K,V>();
        m.put(k1, v1);
        m.put(k2, v2);
        return m;
    }
}

احتضان الشعير والعلم في المعرفة يرتدي زملائك في العملات الخاصة بك نفس الأغلال كما أنت.

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