2008-09-18 16 views
51

मेरे पास है:जावा क्रमबद्धता

class MyClass extends MyClass2 implements Serializable { 
    //... 
} 

MyClass2 में एक संपत्ति है कि serializable नहीं है। मैं इस ऑब्जेक्ट को क्रमबद्ध (और डी-क्रमबद्ध) कैसे कर सकता हूं?

सुधार: MyClass2 निश्चित रूप से एक इंटरफ़ेस नहीं बल्कि एक वर्ग है।

+0

आप MyClass2 को संशोधित करने या नहीं कर सकता:

यहाँ एक उदाहरण है कि कैसे kryo

Kryo kryo = new Kryo(); // #### Store to disk... Output output = new Output(new FileOutputStream("file.bin")); SomeClass someObject = ... kryo.writeObject(output, someObject); output.close(); // ### Restore from disk... Input input = new Input(new FileInputStream("file.bin")); SomeClass someObject = kryo.readObject(input, SomeClass.class); input.close(); 

धारावाहिक वस्तुओं का उपयोग करने के लिए है भी सटीक serializer पंजीकरण से संकुचित किया जा सकता है? क्या सीरियलाइजेशन द्वारा गैर-क्रमिक संपत्ति मूल्य को संरक्षित करने की आवश्यकता है? सही दृष्टिकोण इस पर निर्भर करता है। – erickson

+0

MyClass2 को संशोधित किया जा सकता है। हालांकि, यह बेहतर नहीं होगा, क्योंकि मैं इसके शीर्ष पर बना हूं और इसे दूसरों द्वारा संशोधित किया जा सकता है। – Burkhard

उत्तर

49

जैसा कि किसी और ने उल्लेख किया है, जोश ब्लोच के Effective Java के अध्याय 11 जावा सीरियलाइजेशन पर एक अनिवार्य संसाधन है।

कि अध्याय अपने प्रश्न का उचित से एक जोड़े को अंक:

  • मानते हुए कि आपके MyClass2 में गैर serializable क्षेत्र के राज्य को क्रमानुसार करना चाहते हैं, उस क्षेत्र, MyClass के लिए सुलभ होना चाहिए या तो सीधे या टिककर खेल के माध्यम से और सेटर्स। MyClass को readObject और writeObject विधियों को प्रदान करके कस्टम क्रमिकरण को कार्यान्वित करना होगा।
  • गैर-धारावाहिक फ़ील्ड क्लास में एपीआई होना चाहिए ताकि वह राज्य (ऑब्जेक्ट स्ट्रीम पर लिखने के लिए) प्राप्त कर सके और उसके बाद उस स्थिति के साथ एक नया उदाहरण तत्काल (जब बाद में ऑब्जेक्ट स्ट्रीम से पढ़ा जा सके)
  • प्रति आइटम प्रभावी जावा के 74, MyClass2 में MyClass के लिए कोई नो-Arg कन्स्ट्रक्टर उपलब्ध नहीं है, अन्यथा MyClass के लिए MyClass2 का विस्तार करना और Serializable लागू करना असंभव है।

मैंने इसे चित्रित करने के नीचे एक त्वरित उदाहरण लिखा है।


class MyClass extends MyClass2 implements Serializable{ 

    public MyClass(int quantity) { 
    setNonSerializableProperty(new NonSerializableClass(quantity)); 
    } 

    private void writeObject(java.io.ObjectOutputStream out) 
    throws IOException{ 
    // note, here we don't need out.defaultWriteObject(); because 
    // MyClass has no other state to serialize 
    out.writeInt(super.getNonSerializableProperty().getQuantity()); 
    } 

    private void readObject(java.io.ObjectInputStream in) 
    throws IOException { 
    // note, here we don't need in.defaultReadObject(); 
    // because MyClass has no other state to deserialize 
    super.setNonSerializableProperty(new NonSerializableClass(in.readInt())); 
    } 
} 

/* this class must have no-arg constructor accessible to MyClass */ 
class MyClass2 { 

    /* this property must be gettable/settable by MyClass. It cannot be final, therefore. */ 
    private NonSerializableClass nonSerializableProperty; 

    public void setNonSerializableProperty(NonSerializableClass nonSerializableProperty) { 
    this.nonSerializableProperty = nonSerializableProperty; 
    } 

    public NonSerializableClass getNonSerializableProperty() { 
    return nonSerializableProperty; 
    } 
} 

class NonSerializableClass{ 

    private final int quantity; 

    public NonSerializableClass(int quantity){ 
    this.quantity = quantity; 
    } 

    public int getQuantity() { 
    return quantity; 
    } 
} 
+6

ओह मैं किसी तरह की उम्मीद कर रहा था @NonSerialization की तरह एनोटेशन की: - / –

33

MyClass2 सिर्फ एक इंटरफ़ेस है इसलिए तकनीकी रूप से इसमें कोई गुण नहीं है, केवल विधियां हैं। ऐसा कहा जा रहा है कि यदि आपके पास आवृत्ति चर हैं जो खुद को क्रमबद्ध नहीं हैं, तो मुझे लगता है कि उन क्षेत्रों को क्षणिक घोषित करना एकमात्र तरीका है।

पूर्व:

private transient Foo foo; 

जब आप एक क्षेत्र क्षणिक यह क्रमबद्धता और deserialization प्रक्रिया के दौरान नजरअंदाज कर दिया जाएगा घोषणा करते हैं। ध्यान रखें कि जब आप किसी ऑब्जेक्ट को एक क्षणिक फ़ील्ड के साथ deserialize करते हैं कि फ़ील्ड का मान हमेशा डिफ़ॉल्ट होगा (आमतौर पर शून्य)

नोट करें कि आप क्षणिक फ़ील्ड आधारित प्रारंभ करने के लिए अपनी कक्षा के readResolve() विधि को ओवरराइड भी कर सकते हैं अन्य सिस्टम राज्य पर।

6

आपको writeObject() और readObject() लागू करने और उन क्षेत्रों के मैन्युअल क्रमिकरण/deserialization को लागू करने की आवश्यकता होगी। विवरण के लिए java.io.Serializable के लिए javadoc पृष्ठ देखें। जोश ब्लोच का प्रभावी जावा में मजबूत और सुरक्षित क्रमबद्धीकरण को लागू करने के कुछ अच्छे अध्याय भी हैं।

4

आप क्षणिक कीवर्ड देखकर शुरू कर सकते हैं, जो किसी ऑब्जेक्ट की लगातार स्थिति का हिस्सा नहीं है।

11

यदि आप MyClass2 को संशोधित कर सकते हैं, तो इसका समाधान करने का सबसे आसान तरीका संपत्ति क्षणिक घोषित करता है।

+0

यह प्रश्न का उत्तर नहीं देता है - प्रश्न बताता है कि MyClass2 में ऐसी संपत्ति है जो धारावाहिक नहीं है, और आदर्श MyClass2 को संशोधित नहीं किया जाना चाहिए। –

+0

आप सही हैं, मैंने जवाब का जवाब बहुत सावधानी से वापस नहीं पढ़ा जब मैंने इसका उत्तर दिया। मैंने जवाब संशोधित किया। – ykaganovich

3

XStream किसी भी ऑब्जेक्ट के लिए एक्सएमएल सीरियलाइजेशन के लिए तेज़ जावा करने के लिए एक महान लाइब्रेरी है, इससे कोई फर्क नहीं पड़ता कि यह सीरियलज़ेबल है या नहीं। यहां तक ​​कि यदि XML लक्ष्य प्रारूप आपके अनुरूप नहीं है, तो आप यह जानने के लिए स्रोत कोड का उपयोग कर सकते हैं कि यह कैसे करें।

+0

नमस्ते, क्या आप एक्सस्ट्रीम का उपयोग गैर धारावाहिक वस्तु के साथ कैसे कर सकते हैं? – SWAppDev

+0

दस्तावेज़ीकरण बहुत आत्म-स्पष्टीकरणपूर्ण है, ट्यूटोरियल कक्षाओं से शुरू होता है जो Serializable को लागू नहीं करते हैं और आपको दिखाते हैं कि उन्हें क्रमबद्ध कैसे करें: http://x-stream.github.io/tutorial.html –

5

निर्भर करता है कि MyClass2 का वह सदस्य धारावाहिक नहीं है।

यदि कुछ अच्छा कारण है कि MyClass2 को क्रमबद्ध रूप में क्यों प्रदर्शित नहीं किया जा सकता है, तो संभावनाएं अच्छी हैं, यही कारण है कि MyClass पर लागू होता है, क्योंकि यह उप-वर्ग है।

रीडऑब्जेक्ट और writeObject को लागू करके MyClass के लिए एक कस्टम धारावाहिक रूप लिखना संभव हो सकता है, इस तरह से MyClass में MyClass2 इंस्टेंस डेटा की स्थिति क्रमबद्ध डेटा से उपयुक्त रूप से पुनर्निर्मित की जा सकती है। MyClass2 की API को ठीक करने के लिए यह तरीका होगा और आप Serializable नहीं जोड़ सकते हैं।

लेकिन सबसे पहले आपको यह पता लगाना चाहिए कि MyClass2 क्यों क्रमबद्ध नहीं है, और शायद इसे बदल सकता है।

2

गैर serializable वर्गों के उदाहरण serialising के लिए एक उपयोगी दृष्टिकोण (या कम से कम उपवर्गों में) एक सीरियल प्रॉक्सी जाना जाता है। अनिवार्य रूप से आप एक पूरी तरह से अलग धारावाहिक वर्ग का एक उदाहरण लौटने के लिए लिखने के लिए जगह को लागू करते हैं जो पढ़ता है मूल वस्तु की एक प्रति वापस करने के लिए पुन: प्रयास करें। मैं Usenet

4

कई संभावनाओं पर java.awt.BasicStroke serialising का एक उदाहरण लिखा बाहर poped और मैं उन्हें यहां फिर से शुरू:

  • लागू writeObject() और readObject() sk के रूप में सुझाव
  • संपत्ति की घोषणा क्षणिक और के रूप में boris-terzic
  • द्वारा कहा गया एक सीरियल प्रॉक्सी का उपयोग के रूप मेंद्वारा कहा गया यह पहली hank
  • उपयोग Xstream ने कहा के रूप में धारावाहिक नहीं की जाएगी
15

यदि संभव हो तो, गैर serialiable भागों नहीं तो आप Kryo उपयोग कर सकते हैं क्षणिक

private transient SomeClass myClz; 

के रूप में स्थापित किया जा सकता है। क्रायो जावा के लिए एक तेज़ और कुशल ऑब्जेक्ट ग्राफ़ सीरियलाइजेशन फ्रेमवर्क है (उदाहरण के लिए जावा.ए.टी.ए. के जवा सीरियलाइजेशन को 170 बाइट्स, क्रियो केवल 4 बाइट्स की आवश्यकता होती है), जो गैर धारावाहिक वस्तुओं को क्रमबद्ध भी कर सकती है। क्रियो स्वचालित गहरी और उथली प्रतिलिपि/क्लोनिंग भी कर सकता है। यह ऑब्जेक्ट से ऑब्जेक्ट की प्रतिलिपि है, object->bytes->object नहीं।

kryo.register(SomeObject.class, new DeflateCompressor(new FieldSerializer(kryo, SomeObject.class))); 
संबंधित मुद्दे