java एक serialVersionUID क्या है और मुझे इसका उपयोग क्यों करना चाहिए?




serialization (17)

जब कोई serialVersionUID गुम हो जाता है तो ग्रहण चेतावनी जारी serialVersionUID है।

Serializable वर्ग फू प्रकार के एक स्थिर अंतिम धारावाहिक VersionUID क्षेत्र घोषित नहीं करता है

serialVersionUID क्या है और यह महत्वपूर्ण क्यों है? कृपया एक उदाहरण दिखाएं जहां गायब serialVersionUID एक समस्या का कारण बन जाएगा।


परेशान न करें, 99, 99 99% मामलों के लिए डिफ़ॉल्ट गणना वास्तव में अच्छी और पर्याप्त है। और यदि आप समस्याओं में भाग लेते हैं, तो आप कर सकते हैं - जैसा कि पहले से ही कहा गया है - यूआईडी को आवश्यकता तीर के रूप में पेश करें (जो बेहद असंभव है)


प्रत्येक बार ऑब्जेक्ट को क्रमबद्ध किया जाता है, ऑब्जेक्ट को ऑब्जेक्ट क्लास के लिए संस्करण आईडी संख्या के साथ मुद्रित किया जाता है। इस आईडी को serialVersionUID कहा जाता है और इसे कक्षा संरचना के बारे में जानकारी के आधार पर गणना की जाती है। मान लीजिए कि आपने एक कर्मचारी वर्ग बनाया है और इसमें संस्करण आईडी # 333 (जेवीएम द्वारा असाइन किया गया है), अब जब आप उस वर्ग (ऑब्जेक्ट ऑब्जेक्ट का मान लें) की ऑब्जेक्ट को क्रमबद्ध करेंगे, तो JVM इसे यूआईडी को # 333 के रूप में असाइन करेगा।

किसी स्थिति पर विचार करें - भविष्य में आपको अपनी कक्षा को संपादित या बदलने की आवश्यकता है और उस स्थिति में जब आप इसे संशोधित करते हैं, तो JVM इसे एक नया यूआईडी (मान लीजिए # 444) असाइन करेगा। अब जब आप कर्मचारी ऑब्जेक्ट को deserialize करने का प्रयास करते हैं, तो JVM कक्षा के अर्थात् # 444 (क्योंकि यह बदला गया था) के साथ क्रमबद्ध ऑब्जेक्ट (कर्मचारी ऑब्जेक्ट) संस्करण आईडी (# 333) की तुलना करेगा। तुलनात्मक रूप से जेवीएम दोनों संस्करण यूआईडी अलग-अलग पाएंगे और इसलिए Deserialization विफल हो जाएगा। इसलिए यदि प्रत्येक वर्ग के लिए serialVersionID प्रोग्रामर द्वारा स्वयं परिभाषित किया गया है। यह भविष्य में विकसित होने के बावजूद भी होगा और इसलिए जेवीएम हमेशा यह मान लेगा कि कक्षा क्रमबद्ध वस्तु के साथ संगत है, भले ही कक्षा बदल दी गई हो। अधिक जानकारी के लिए आप हेड प्रथम जावा के अध्याय 14 का उल्लेख कर सकते हैं।


मैं जोश ब्लोच की पुस्तक प्रभावी जावा (द्वितीय संस्करण) को प्लग करने के लिए इस अवसर को पार नहीं कर सकता। अध्याय 11 जावा क्रमबद्धता पर एक अनिवार्य संसाधन है।

प्रति जोश, स्वचालित रूप से जेनरेट की गई यूआईडी कक्षा के नाम, कार्यान्वित इंटरफेस, और सभी सार्वजनिक और संरक्षित सदस्यों के आधार पर उत्पन्न होती है। इनमें से किसी भी तरह से किसी भी तरह से बदलना serialVersionUID बदल जाएगा। इसलिए आपको केवल उनके साथ गड़बड़ करने की आवश्यकता नहीं है यदि आप निश्चित हैं कि कक्षा के एक से अधिक संस्करणों को कभी भी क्रमबद्ध नहीं किया जाएगा (या तो प्रक्रियाओं में या बाद में भंडारण से पुनर्प्राप्त)।

यदि आप उन्हें अभी अनदेखा करते हैं, और बाद में पाते हैं कि आपको कक्षा को किसी भी तरह से बदलने की आवश्यकता है, लेकिन कक्षा के संगतता w / पुराने संस्करण को बनाए रखने के लिए, आप पुराने वर्ग पर serialVersionUID उत्पन्न करने के लिए जेडीके टूल धारावाहिक का उपयोग कर सकते हैं, और स्पष्ट रूप से सेट कर सकते हैं कि नई कक्षा में। (आपके परिवर्तनों के आधार पर आपको writeObject और readObject विधियों को जोड़कर कस्टम readObject को भी लागू करने की आवश्यकता हो सकती है - Serializable javadoc या उपरोक्त अध्याय 11 देखें)


यह सवाल यहोशू ब्लोच द्वारा प्रभावी जावा में बहुत अच्छी तरह से प्रलेखित है। एक बहुत अच्छी किताब और एक पढ़ा जाना चाहिए। मैं नीचे दिए गए कुछ कारणों की रूपरेखा तैयार करूंगा:

क्रमबद्धता रनटाइम प्रत्येक धारावाहिक वर्ग के लिए सीरियल संस्करण नामक एक संख्या के साथ आता है। इस नंबर को serialVersionUID कहा जाता है। अब इस संख्या के पीछे कुछ गणित है और यह वर्ग में परिभाषित फ़ील्ड / विधियों के आधार पर आता है। उसी कक्षा के लिए हर बार एक ही संस्करण उत्पन्न होता है। यह संख्या deserialization के दौरान यह सत्यापित करने के लिए प्रयोग किया जाता है कि एक धारावाहिक वस्तु के प्रेषक और रिसीवर ने उस ऑब्जेक्ट के लिए कक्षाएं लोड की हैं जो क्रमबद्धता के संबंध में संगत हैं। यदि रिसीवर ने ऑब्जेक्ट के लिए एक वर्ग लोड किया है जिसमें संबंधित प्रेषक वर्ग की तुलना में एक अलग धारावाहिक VersionUID है, तो deserialization के परिणामस्वरूप एक अवैध क्लास अपवाद होगा।

यदि कक्षा क्रमबद्ध है तो आप "serialVersionUID" नामक फ़ील्ड घोषित करके स्पष्ट रूप से अपना स्वयं का धारावाहिक VERSIONUID घोषित कर सकते हैं जो स्थिर, अंतिम और प्रकार का लंबा होना चाहिए। अधिकांश आईडीई की तरह ग्रहण आपको उस लंबी स्ट्रिंग को उत्पन्न करने में मदद करता है।


java.io.Serializable लिए दस्तावेज़ संभवतः एक स्पष्टीकरण के बारे में हैं जो आपको मिलेगा:

क्रमबद्ध रनटाइम प्रत्येक धारावाहिक वर्ग के साथ एक संस्करण संख्या के साथ संबद्ध होता है, जिसे एक serialVersionUID कहा जाता है, जिसे deserialization के दौरान प्रयोग किया जाता है ताकि यह सत्यापित किया जा सके कि एक धारावाहिक वस्तु के प्रेषक और रिसीवर ने उस ऑब्जेक्ट के लिए कक्षाएं लोड की हैं जो क्रमबद्धता के संबंध में संगत हैं। यदि रिसीवर ने ऑब्जेक्ट के लिए एक वर्ग लोड किया है जिसमें संबंधित प्रेषक वर्ग की तुलना में एक अलग serialVersionUID है, तो deserialization के परिणामस्वरूप एक serialVersionUID होगा। एक धारावाहिक वर्ग धारावाहिक serialVersionUID नामक एक फ़ील्ड घोषित करके स्पष्ट रूप से अपने स्वयं के serialVersionUID घोषित कर सकता है जो स्थैतिक, अंतिम और प्रकार का होना चाहिए:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

यदि एक धारावाहिक वर्ग स्पष्ट रूप से एक serialVersionUID घोषित नहीं करता है, तो serialization रनटाइम जावा (टीएम) ऑब्जेक्ट सीरियलाइजेशन विशिष्टता में वर्णित अनुसार, कक्षा के विभिन्न पहलुओं के आधार पर उस कक्षा के लिए एक डिफ़ॉल्ट serialVersionUID मान की गणना करेगा। हालांकि, यह दृढ़ता से अनुशंसा की जाती है कि सभी धारावाहिक वर्ग स्पष्ट रूप से serialVersionUID मानों की घोषणा serialVersionUID हैं, क्योंकि डिफ़ॉल्ट serialVersionUID गणना कक्षा विवरणों के प्रति अत्यधिक संवेदनशील होती है जो संकलक कार्यान्वयन के आधार पर भिन्न हो सकती हैं, और इस प्रकार deserialization के दौरान अप्रत्याशित अवैध क्लास serialVersionUID परिणाम हो सकता है। इसलिए, विभिन्न जावा कंपाइलर कार्यान्वयन में एक सतत serialVersionUID मान की गारंटी के लिए, एक धारावाहिक वर्ग को एक स्पष्ट serialVersionUID मान घोषित करना होगा। यह भी दृढ़ता से सलाह दी जाती है कि स्पष्ट serialVersionUID घोषणाएं जहां संभव हो, निजी संशोधक का उपयोग करें, क्योंकि ऐसी घोषणाएं केवल तुरंत घोषित कक्षा serialVersionUID फ़ील्ड पर लागू होती हैं जो विरासत वाले सदस्यों के रूप में उपयोगी नहीं होती हैं।


यह अच्छा होगा अगर चेकस्टाइल सत्यापित कर सके कि SerialVersionUID एक वर्ग पर जो Serializable लागू करता है, का एक अच्छा मूल्य है, यानी यह धारावाहिक संस्करण आईडी जनरेटर का उत्पादन करेगा। यदि आपके पास बहुत सी धारावाहिक डीटीओ के साथ एक परियोजना है, उदाहरण के लिए, मौजूदा धारावाहिक VERSIONUID को हटाने और इसे पुनर्जीवित करना याद रखना एक दर्द है, और वर्तमान में यह सत्यापित करने का एकमात्र तरीका (जिसे मैं जानता हूं) प्रत्येक वर्ग के लिए पुन: उत्पन्न करना और तुलना करना है पुराना वाला। यह बहुत दर्दनाक है।


आप इन serialVersionUID चेतावनियों को अनदेखा करने के लिए ग्रहण को बता सकते हैं:

विंडो> वरीयताएँ> जावा> कंपाइलर> त्रुटियां / चेतावनियां> संभावित प्रोग्रामिंग समस्याएं

यदि आपको पता नहीं था, तो इस अनुभाग में कई अन्य चेतावनियां सक्षम हो सकती हैं (या यहां तक ​​कि कुछ त्रुटियों के रूप में भी रिपोर्ट की गई हैं), कई बहुत उपयोगी हैं:

  • संभावित प्रोग्रामिंग समस्याएं: संभावित आकस्मिक बूलियन असाइनमेंट
  • संभावित प्रोग्रामिंग समस्याएं: शून्य सूचक पहुंच
  • अनावश्यक कोड: स्थानीय चर कभी नहीं पढ़ा जाता है
  • अनावश्यक कोड: अनावश्यक शून्य जांच
  • अनावश्यक कोड: अनावश्यक कास्ट या 'उदाहरण'

और बहुत सारे।


एक serialVersionUID क्या है और मुझे इसका उपयोग क्यों करना चाहिए?

SerialVersionUID प्रत्येक वर्ग के लिए एक अद्वितीय पहचानकर्ता है, JVM वर्ग के संस्करणों की तुलना करने के लिए इसका उपयोग करता है यह सुनिश्चित करता है कि सीरियलाइजेशन के दौरान उसी वर्ग का उपयोग Deserialization के दौरान लोड किया गया हो।

निर्दिष्ट करना अधिक नियंत्रण देता है, यद्यपि यदि आप निर्दिष्ट नहीं करते हैं तो JVM एक उत्पन्न करता है। जेनरेट किया गया मान अलग-अलग कंपाइलरों के बीच भिन्न हो सकता है। इसके अलावा, कभी-कभी आप पुराने धारावाहिक वस्तुओं [ backward incompatibility ] के deserialization को मना करने के लिए कुछ कारण चाहते हैं, और इस मामले में आपको केवल serialVersionUID को बदलना होगा।

Serializable लिए javadocs कहते हैं :

डिफ़ॉल्ट serialVersionUID गणना कक्षा विवरणों के प्रति अत्यधिक संवेदनशील है जो संकलक कार्यान्वयन के आधार पर भिन्न हो सकती है, और इस प्रकार deserialization के दौरान अप्रत्याशित अवैध क्लास अपवाद का परिणाम हो सकता है।

इसलिए, आपको serialVersionUID घोषित करना होगा क्योंकि यह हमें अधिक नियंत्रण प्रदान करता है

इस आलेख में विषय पर कुछ अच्छे अंक हैं।


यदि आपको कक्षा में यह चेतावनी मिलती है तो आप कभी भी धारावाहिक करने के बारे में नहीं सोचते हैं, और आपने स्वयं implements Serializable नहीं किया है, ऐसा अक्सर होता है क्योंकि आप सुपरक्लास से विरासत में रहते हैं, जो सीरियलज़ेबल लागू करता है। अक्सर विरासत का उपयोग करने के बजाय ऐसी वस्तु को प्रतिनिधि करना बेहतर होगा।

तो, इसके बजाय

public class MyExample extends ArrayList<String> {

    public MyExample() {
        super();
    }
    ...
}

करना

public class MyExample {
    private List<String> myList;

    public MyExample() {
         this.myList = new ArrayList<String>();
    }
    ...
}

और प्रासंगिक तरीकों में this.foo() (या super.foo() ) के बजाय myList.foo() कॉल करें। (यह सभी मामलों में फिट नहीं है, लेकिन अभी भी अक्सर।)

मैं अक्सर जेएफआरएएम या ऐसे लोगों को विस्तारित करने वाले लोगों को देखता हूं, जब उन्हें वास्तव में केवल इस पर प्रतिनिधि होना पड़ता है। (यह आईडीई में स्वत: पूर्ण करने में भी मदद करता है, क्योंकि जेएफआरएएम में सैकड़ों विधियां हैं, जिनकी आवश्यकता नहीं है जब आप अपनी कक्षा में अपने कस्टम लोगों को कॉल करना चाहते हैं।)

एक मामला जहां चेतावनी (या serialVersionUID) अपरिहार्य है, जब आप सार तत्व से सामान्य रूप से अज्ञात वर्ग में विस्तार करते हैं, केवल क्रिया-स्वरूपित-विधि जोड़ते हैं। मुझे लगता है कि इस मामले में कोई चेतावनी नहीं होनी चाहिए (क्योंकि आप आमतौर पर अपने वर्ग के विभिन्न संस्करणों के पार इस तरह के अज्ञात वर्गों को विश्वसनीय क्रमबद्ध और deserialize नहीं कर सकते हैं), लेकिन मुझे यकीन नहीं है कि संकलक इसे कैसे पहचान सकता है।


क्षेत्र serialVersionUID के महत्व को समझने के लिए, किसी को समझना चाहिए कि सीरियलाइजेशन / Deserialization कैसे काम करता है।

जब एक सीरियलज़ेबल क्लास ऑब्जेक्ट को क्रमबद्ध किया जाता है तो जावा रनटाइम इस धारावाहिक ऑब्जेक्ट के साथ एक सीरियल संस्करण संख्या (जिसे serialVersionUID कहा जाता है) को जोड़ता है। उस समय जब आप इस धारावाहिक वस्तु को deserialize जावा रनटाइम धारावाहिक ऑब्जेक्ट के serialVersionUID से कक्षा के serialVersionUID के साथ मेल खाता है। यदि दोनों बराबर हैं तो केवल यह deserialization की आगे की प्रक्रिया के साथ आगे बढ़ता है और अन्य अवैध क्लास अपवाद फेंकता है।

तो हम निष्कर्ष निकाला है कि सीरियलाइजेशन / डेसेरियलाइजेशन प्रक्रिया को सफल बनाने के लिए धारावाहिक वस्तु का serialVersionUID कक्षा के serialVersionUID के बराबर होना चाहिए। यदि प्रोग्रामर प्रोग्राम में स्पष्ट रूप से serialVersionUID मान निर्दिष्ट करता है तो उसी मान को क्रमबद्ध ऑब्जेक्ट और क्लास से जोड़ा जाएगा, चाहे सीरियलाइजेशन और deserialzation प्लेटफ़ॉर्म के बावजूद (उदाहरण के लिए सूर्य का उपयोग करके खिड़कियों जैसे मंच पर किया जा सकता है। एमएस जेवीएम और Deserialization ज़िंग JVM का उपयोग कर विभिन्न मंच लिनक्स पर हो सकता है)।

लेकिन अगर serialVersionUID प्रोग्रामर द्वारा निर्दिष्ट नहीं किया गया है तो किसी भी ऑब्जेक्ट के सीरियलाइजेशन \ DeSerialization करते समय, जावा रनटाइम इसकी गणना करने के लिए अपने स्वयं के एल्गोरिदम का उपयोग करता है। यह serialVersionUID गणना एल्गोरिदम एक जेआरई से दूसरे में भिन्न होता है। यह भी संभव है कि जिस वस्तु को ऑब्जेक्ट किया गया है, वह एक जेआरई (पूर्व: सूर्य जेवीएम) और पर्यावरण जहां deserialzation होता है, लिनक्स जेवीएम (ज़िंग) का उपयोग कर रहा है। ऐसे मामलों में धारावाहिक वस्तु से जुड़े serialVersionUID deserialzation पर्यावरण पर गणना की कक्षा के serialVersionUID से अलग होगा। बदले में deserialization सफल नहीं होगा। इसलिए ऐसी स्थितियों / मुद्दों से बचने के लिए प्रोग्रामर को हमेशा सेरिअलाइज़ेबल क्लास के serialVersionUID निर्दिष्ट करना होगा।


serialVersionUID क्रमबद्ध डेटा के संस्करण को सुविधाजनक बनाता है। धारावाहिक होने पर इसका मूल्य डेटा के साथ संग्रहीत किया जाता है। डी-सीरियलाइजिंग करते समय, समान संस्करण को जांचने के लिए जांच की जाती है कि धारावाहिक डेटा वर्तमान कोड से कैसे मेल खाता है।

यदि आप अपने डेटा को संस्करण बनाना चाहते हैं, तो आप आमतौर पर 0 के एक serialVersionUID से शुरू करते हैं, और इसे अपनी कक्षा में प्रत्येक संरचनात्मक परिवर्तन के साथ टक्कर देते हैं जो क्रमबद्ध डेटा को बदलता है (गैर-क्षणिक फ़ील्ड जोड़ना या निकालना)।

अंतर्निहित डी-सीरियलाइजेशन तंत्र ( in.defaultReadObject() ) डेटा के पुराने संस्करणों से डी-क्रमबद्ध करने से इंकार कर देगा। लेकिन यदि आप चाहते हैं कि आप अपना खुद का readObject() परिभाषित कर सकें जो पुराने डेटा को वापस पढ़ सके। यह कस्टम कोड तब यह serialVersionUID लिए serialVersionUID जांच कर सकता है कि डेटा किस संस्करण में है और यह तय करें कि इसे डी-सीरियलाइज़ कैसे करें। यह वर्जनिंग तकनीक उपयोगी है यदि आप धारावाहिक डेटा संग्रहीत करते हैं जो आपके कोड के कई संस्करणों से बचती है।

लेकिन इस तरह के लंबे समय के लिए धारावाहिक डेटा भंडारण बहुत आम नहीं है। सीरियलाइजेशन तंत्र का उपयोग अस्थायी रूप से डेटा को कैश करने के लिए या कोडबेज के प्रासंगिक हिस्सों के समान संस्करण के साथ नेटवर्क पर किसी अन्य प्रोग्राम में भेजने के लिए करना अधिक सामान्य है।

इस मामले में आप पिछड़ा संगतता बनाए रखने में रुचि नहीं रखते हैं। आप केवल यह सुनिश्चित करने के लिए चिंतित हैं कि कोड बेस जो वास्तव में संचार कर रहे हैं, प्रासंगिक वर्गों के समान संस्करण हैं। इस तरह की जांच को सुविधाजनक बनाने के लिए, आपको पहले से ही serialVersionUID को बनाए रखना होगा और अपनी कक्षाओं में बदलाव करते समय इसे अपडेट करना न भूलें।

यदि आप फ़ील्ड को अपडेट करना भूल जाते हैं, तो आप अलग-अलग संरचना वाले वर्ग के दो अलग-अलग संस्करणों के साथ समाप्त हो सकते हैं लेकिन उसी serialVersionUID । यदि ऐसा होता है, तो डिफ़ॉल्ट तंत्र ( in.defaultReadObject() ) किसी भी अंतर का पता नहीं लगाएगा, और असंगत डेटा को डी-क्रमबद्ध करने का प्रयास करेगा। अब आप एक क्रिप्टिक रनटाइम त्रुटि या मूक विफलता (शून्य फ़ील्ड) के साथ समाप्त हो सकते हैं। इन प्रकार की त्रुटियों को ढूंढना मुश्किल हो सकता है।

तो इस उपयोगकेस की सहायता के लिए, जावा प्लेटफ़ॉर्म आपको मैन्युअल रूप से serialVersionUID सेट करने का विकल्प प्रदान करता है। इसके बजाए, कक्षा संरचना का एक हैश संकलन समय पर उत्पन्न किया जाएगा और आईडी के रूप में उपयोग किया जाएगा। यह तंत्र यह सुनिश्चित करेगा कि आपके पास एक ही आईडी के साथ अलग-अलग वर्ग संरचनाएं न हों, और इसलिए आपको ऊपर वर्णित इन हार्ड-टू-ट्रेस रनटाइम क्रमिक विफलताओं को नहीं मिलेगा।

लेकिन ऑटो-जनरेटेड आईडी रणनीति का पिछड़ा हिस्सा है। अर्थात् एक ही कक्षा के लिए जेनरेटेड आईडी कंपिलरों के बीच भिन्न हो सकती हैं (जैसा कि उपरोक्त जॉन स्कीट द्वारा उल्लिखित है)। इसलिए यदि आप अलग-अलग कंपाइलरों के साथ संकलित कोड के बीच धारावाहिक डेटा को संवाद करते हैं, तो वैसे भी आईडी को मैन्युअल रूप से बनाए रखने की अनुशंसा की जाती है।

और यदि आप पीछे दिए गए हैं- आपके डेटा के साथ संगत पहले उपयोग मामले में संगत, तो आप शायद आईडी को स्वयं भी बनाए रखना चाहते हैं। यह पठनीय आईडी प्राप्त करने के लिए और कब और कैसे बदलता है पर अधिक नियंत्रण है।


यदि आपको अपनी ऑब्जेक्ट को बाइट सरणी में क्रमबद्ध करने और उन्हें भेजने / स्टोर करने की आवश्यकता नहीं होगी, तो आपको इसके बारे में चिंता करने की आवश्यकता नहीं है। यदि आप करते हैं, तो आपको अपने serialVersionUID पर विचार करना चाहिए क्योंकि ऑब्जेक्ट का deserializer इसे अपने क्लासलोडर के ऑब्जेक्ट के संस्करण से मेल करेगा। जावा भाषा विशिष्टता में इसके बारे में और पढ़ें।


सबसे पहले मुझे क्रमबद्धरण की व्याख्या करने की आवश्यकता है।
सीरियलाइजेशन ऑब्जेक्ट को नेटवर्क पर उस ऑब्जेक्ट को भेजने के लिए ऑब्जेक्ट को स्ट्रीम करने या फ़ाइल में सहेजने या अक्षर उपयोग के लिए डीबी में सहेजने की अनुमति देता है।

Serialization के लिए कुछ नियम हैं

  • एक वस्तु केवल serializable है अगर इसकी कक्षा या इसके superclass serializable इंटरफ़ेस लागू करता है

  • एक ऑब्जेक्ट serializable है (स्वयं serializable इंटरफ़ेस लागू करता है) भले ही इसका सुपरक्लास नहीं है। हालांकि, serializable वर्ग के पदानुक्रम में पहला सुपरक्लास, जो Serializable इंटरफेस लागू नहीं करता है, एक नो-Arg कन्स्ट्रक्टर होना चाहिए। यदि इसका उल्लंघन किया जाता है, तो readObject () रनटाइम में java.io.InvalidClassException उत्पन्न करेगा

  • सभी आदिम प्रकार serializable हैं।

  • क्षणिक फ़ील्ड (क्षणिक संशोधक के साथ) क्रमबद्ध नहीं हैं, (यानी, सहेजा या बहाल नहीं किया गया)। एक वर्ग जो Serializable लागू करता है उन वर्गों के क्षणिक फ़ील्ड को चिह्नित करना चाहिए जो serialization (उदाहरण के लिए, एक फ़ाइल स्ट्रीम) का समर्थन नहीं करते हैं।

  • स्टेटिक फ़ील्ड (स्थिर संशोधक के साथ) क्रमबद्ध नहीं हैं।

जब ऑब्जेक्ट को क्रमबद्ध किया जाता है तो जावा रनटाइम सीरियल संस्करण संख्या को संबद्ध करता है जिसे धारावाहिक VersionID कहा जाता है।

जहां हमें serialVersionID की आवश्यकता है: यह सत्यापित करने के लिए deserialization के दौरान प्रेषक और रिसीवर serialization के संबंध में संगत हैं। अगर रिसीवर अलग serialVersionID के साथ वर्ग लोड किया तो deserialization अवैध क्लासकास्टएक्सप्शन के साथ खत्म हो जाएगा।
एक धारावाहिक वर्ग "serialVersionUID" नामक फ़ील्ड घोषित करके स्पष्ट रूप से स्थिर, अंतिम और प्रकार का होना चाहिए:।

आइए इसे एक उदाहरण के साथ आज़माएं।

import java.io.Serializable;    
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String empname;
private byte empage;

public String getEmpName() {
    return name;
}
public void setEmpName(String empname) {
    this.empname = empname;
}
public byte getEmpAge() {
    return empage;
}
public void setEmpAge(byte empage) {
    this.empage = empage;
}

public String whoIsThis() {
    StringBuffer employee = new StringBuffer();
    employee.append(getEmpName()).append(" is ).append(getEmpAge()).append("
years old  "));
    return employee.toString();
}
}

Serialize ऑब्जेक्ट बनाएँ

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Writer {
public static void main(String[] args) throws IOException {
    Employee employee = new Employee();
    employee.setEmpName("Jagdish");
    employee.setEmpAge((byte) 30);

    FileOutputStream fout = new 
FileOutputStream("/users/Jagdish.vala/employee.obj");
    ObjectOutputStream oos = new ObjectOutputStream(fout);
    oos.writeObject(employee);
    oos.close();
    System.out.println("Process complete");
}
}

वस्तु Deserializ

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Reader {
public static void main(String[] args) throws ClassNotFoundException, 
IOException {
    Employee employee = new Employee();
    FileInputStream fin = new 
    FileInputStream("/users/Jagdish.vala/employee.obj");
    ObjectInputStream ois = new ObjectInputStream(fin);
    employee = (Employee) ois.readObject();
    ois.close();
    System.out.println(employee.whoIsThis());
 }
}    

नोट: अब कर्मचारी वर्ग के serialVersionUID को बदलें और सहेजें:

private static final long serialVersionUID = **4L**;

और रीडर वर्ग निष्पादित करें। लेखक वर्ग को निष्पादित नहीं करना है और आपको अपवाद मिलेगा।

Exception in thread "main" java.io.InvalidClassException: 
com.jagdish.vala.java.serialVersion.Employee; local class incompatible: 
stream classdesc serialVersionUID = 1, local class serialVersionUID = 4
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at com.krishantha.sample.java.serialVersion.Reader.main(Reader.java:14)

मूल प्रश्न ने 'यह महत्वपूर्ण क्यों है' और 'उदाहरण' के लिए कहा है जहां यह Serial Version ID उपयोगी होगी। खैर मुझे एक मिला है।

मान लें कि आप एक Car वर्ग बनाते हैं, इसे तुरंत चालू करते हैं, और इसे ऑब्जेक्ट स्ट्रीम में लिखते हैं। फ़्लैटेड कार ऑब्जेक्ट कुछ समय के लिए फाइल सिस्टम में बैठता है। इस बीच, यदि एक नया क्षेत्र जोड़कर Car वर्ग संशोधित किया गया है। बाद में, जब आप फ़्लैटेड Car ऑब्जेक्ट को पढ़ने (यानी deserialize) पढ़ने की कोशिश करते हैं, तो आपको java.io.InvalidClassException मिलता है - क्योंकि सभी धारावाहिक वर्ग स्वचालित रूप से एक अद्वितीय पहचानकर्ता दिए जाते हैं। यह अपवाद फेंक दिया जाता है जब कक्षा का पहचानकर्ता फ़्लैटेड ऑब्जेक्ट के पहचानकर्ता के बराबर नहीं होता है। यदि आप वास्तव में इसके बारे में सोचते हैं, तो नए क्षेत्र के अतिरिक्त होने के कारण अपवाद फेंक दिया जाता है। एक स्पष्ट serialVersionUID घोषित करके आप स्वयं को संस्करण को नियंत्रित करके इस अपवाद को फेंक सकते हैं। स्पष्ट रूप से अपने serialVersionUID घोषित करने में एक छोटा प्रदर्शन लाभ भी है (क्योंकि गणना की आवश्यकता नहीं है)। इसलिए, जैसे ही आप उन्हें नीचे दिखाए गए अनुसार अपने Serializable कक्षाओं में अपना स्वयं का serialVersionUID जोड़ना सबसे अच्छा अभ्यास है:

public class Car {
static final long serialVersionUID = 1L; //assign a long value
}

जावा में कक्षा के SerialVersionUIDअंदर क्यों उपयोग करें Serializable?

के दौरान serialization, जावा रनटाइम कक्षा के लिए संस्करण संख्या बनाता है, ताकि वह इसे बाद में डी-क्रमबद्ध कर सके। यह संस्करण संख्या SerialVersionUIDजावा में जाना जाता है।

SerialVersionUIDसंस्करण धारावाहिक डेटा के लिए प्रयोग किया जाता है। यदि आप SerialVersionUIDधारावाहिक उदाहरण के साथ मेल खाते हैं तो आप केवल कक्षा को डी-क्रमबद्ध कर सकते हैं । जब हम SerialVersionUIDअपनी कक्षा में घोषित नहीं करते हैं , तो जावा रनटाइम इसे हमारे लिए उत्पन्न करता है लेकिन इसकी अनुशंसा नहीं की जाती है। डिफ़ॉल्ट तंत्र से बचने के लिए चर के SerialVersionUIDरूप में घोषित करने की अनुशंसा की जाती है private static final long

जब आप Serializableमार्कर इंटरफेस को कार्यान्वित करके कक्षा घोषित करते हैं java.io.Serializable, तो जावा रनटाइम डिफ़ॉल्ट सीरियलाइजेशन तंत्र का उपयोग कर डिस्क में उस वर्ग का उदाहरण जारी रखता है, बशर्ते आपने Externalizableइंटरफ़ेस का उपयोग करके प्रक्रिया को कस्टमाइज़ नहीं किया हो ।

जावा में Serializable कक्षा के अंदर SerialVersionUID का उपयोग क्यों करें देखें

कोड: javassist.SerialVersionUID


SerialVersionUID ऑब्जेक्ट के संस्करण नियंत्रण के लिए उपयोग किया जाता है। आप अपनी कक्षा फ़ाइल में serialVersionUID भी निर्दिष्ट कर सकते हैं। SerialVersionUID को निर्दिष्ट नहीं करने का नतीजा यह है कि जब आप कक्षा में किसी भी क्षेत्र को जोड़ते या संशोधित करते हैं तो पहले से ही धारावाहिक वर्ग पुनर्प्राप्त नहीं हो पाएगा क्योंकि नई कक्षा के लिए उत्पन्न सीरियलवर्सनयूआईडी और पुराने धारावाहिक वस्तु के लिए अलग-अलग होगा। जावा धारावाहिक प्रक्रिया serialized ऑब्जेक्ट की स्थिति को पुनर्प्राप्त करने के लिए सही serialVersionUID पर निर्भर करती है और serialVersionUID मेलसमूह के मामले में java.io.InvalidClassException फेंकता है

और पढ़ें: http://javarevisited.blogspot.com/2011/04/top-10-java-serialization-interview.html#ixzz3VQxnpOPZ


एक उदाहरण के लिए जहां गायब serialVersionUID एक समस्या का कारण बन सकता है:

मैं इस जावा ईई एप्लिकेशन पर काम कर रहा हूं जो एक वेब मॉड्यूल से बना है जो EJB मॉड्यूल का उपयोग करता है। वेब मॉड्यूल EJB मॉड्यूल को दूरस्थ रूप से कॉल करता है और एक POJO पास करता है जो एक तर्क के रूप में Serializable लागू करता है।

इस POJO's कक्षा को ईजेबी जार के अंदर और वेब मॉड्यूल के वेब-आईएनएफ / lib में अपने स्वयं के जार के अंदर पैक किया गया था। वे वास्तव में एक ही कक्षा में हैं, लेकिन जब मैं ईजेबी मॉड्यूल को पैकेज करता हूं तो मैं इस पीओजेओ के जार को ईजेबी मॉड्यूल के साथ पैक करने के लिए अनपैक करता हूं।

EJB को कॉल नीचे अपवाद के साथ विफल रहा था क्योंकि मैंने अपना serialVersionUID घोषित नहीं किया था:

Caused by: java.io.IOException: Mismatched serialization UIDs : Source
 (Rep.
 IDRMI:com.hordine.pedra.softbudget.domain.Budget:5CF7CE11E6810A36:04A3FEBED5DA4588)
 = 04A3FEBED5DA4588 whereas Target (Rep. ID RMI:com.hordine.pedra.softbudget.domain.Budget:7AF5ED7A7CFDFF31:6227F23FA74A9A52)
 = 6227F23FA74A9A52




serialversionuid