2015-03-14 9 views
15

जब मैं किसी वर्ग से ऑब्जेक्ट को तुरंत चालू करता हूं, तो जावा ऑप में ऑब्जेक्ट सहेजा जाता है। जब मैं ऑब्जेक्ट को क्रमबद्ध करके सहेजता हूं और बाद में मैं ऑब्जेक्ट को deserialize करता हूं, तो क्या मैं सही ढंग से समझता हूं कि ऑब्जेक्ट में अब एक नया ढेर पता होगा लेकिन फिर भी कक्षा का सटीक उदाहरण होगा।एक deserialised वस्तु मूल उदाहरण के रूप में एक ही उदाहरण है

+7

originalObj == deserilized झूठी हो जाएगा लेकिन originalObj.equals (deserilized) सच होना चाहिए। – robbmj

+0

यदि मैं आपको सही ढंग से समझता हूं तो उत्तर नहीं है, तो दो संदर्भ एक ही ऑब्जेक्ट ए – robbmj

+2

पर इंगित नहीं करेंगे यदि आप अपना प्रश्न विस्तृत करना चाहते हैं, तो टिप्पणियों में ऐसा न करें, इसे प्रश्न के मुख्य भाग में करें। टिप्पणियां लंबी चर्चाओं या कोड या प्रारूपित किसी भी स्थान के लिए एक जगह नहीं हैं। – RealSkeptic

उत्तर

20

अपने प्रश्न का उत्तर नहीं हो सकता बस एक हाँ या नहीं। अवधारणा का विश्लेषण करने के लिए आवश्यक है। मैं आपको एक पेंसिल और पेपर लेने का सुझाव दूंगा और इसे नीचे दिये गये बिंदुओं को ध्यान में रखकर स्वयं करूँगा।

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

    enter image description here

    सभी वस्तु एक संदर्भ एक ढेर प्रविष्टि की ओर इशारा करते हैं और आप objectB.getObjectA() की कोशिश करता है, तो =:

संदर्भ आप में ऊपर अवधारणा picturizing के लिए नीचे दिए गए चित्र पर देखो = objectC.getObjectA() या कोई अन्य ऐसा ऑपरेशन, आप सच हो जाएंगे।

केस 1 जब आप वस्तुओं को अलग से बचाने और उन्हें यहाँ deserialize क्या ढेर में होता है:

enter image description here

अब आप पता लगा सकते हैं के रूप में है कि objectBcopy.getObjectA() == objectCcopy। getObjectA() ऑब्जेक्ट ए के संदर्भ के रूप में सही नहीं लौटाएगा कॉपी किए गए ऑब्जेक्ट्स के लिए कोई और नहीं है।

enter image description here

आप पता लगा सकते हैं के रूप में अब है कि:

केस 2 विपरीत, जब आप एक एकल फाइल में वस्तुओं को बचाने और उन्हें बाद में deserialize पर, यहाँ क्या ढेर में होता है objectBcopy.getObjectA() == objectCcopy.getObjectA() अब ऑब्जेक्ट के संदर्भ के रूप में सत्य होगा एक प्रति एक जैसी है, लेकिन यह अभी भी ऑब्जेक्ट ए की एक नई प्रति है।

मेरे कटौती का समर्थन करने के लिए एक त्वरित प्रोग्राम (केस 1 और केस 2):

public class Test{ 

    public static void main (String args[]) throws IOException, ClassNotFoundException{ 
     A a = new A(); 

     B b = new B(); 
     b.a = a; 

     C c = new C(); 
     c.a = a; 

     System.out.println("b.a == c.a is " + (b.a == c.a)); 

     // Case 1 - when two diferent files are used to write the objects 
     FileOutputStream fout = new FileOutputStream("c:\\b.ser"); 
     ObjectOutputStream oos = new ObjectOutputStream(fout); 
     oos.writeObject(b); 
     oos.close(); 
     fout.close(); 

     fout = new FileOutputStream("c:\\c.ser"); 
     oos = new ObjectOutputStream(fout); 
     oos.writeObject(c); 
     oos.close(); 
     fout.close(); 

     FileInputStream fileIn = new FileInputStream("c:\\b.ser"); 
     ObjectInputStream in = new ObjectInputStream(fileIn); 
     B bCopy = (B) in.readObject(); 
     in.close(); 
     fileIn.close(); 

     fileIn = new FileInputStream("c:\\c.ser"); 
     in = new ObjectInputStream(fileIn); 
     C cCopy = (C) in.readObject(); 
     in.close(); 
     fileIn.close(); 
     System.out.println("Case 1 - bCopy.a == cCopy.a is " + (bCopy.a == cCopy.a)); 

     // Case 2 - when both the objects are saved in the same file 
     fout = new FileOutputStream("c:\\both.ser"); 
     oos = new ObjectOutputStream(fout); 
     oos.writeObject(b); 
     oos.writeObject(c); 
     oos.close(); 
     fout.close(); 


     fileIn = new FileInputStream("c:\\both.ser"); 
     in = new ObjectInputStream(fileIn); 
     bCopy = (B) in.readObject(); 
     cCopy = (C) in.readObject(); 
     in.close(); 
     fileIn.close(); 
     System.out.println("Case 2 - bCopy.a == cCopy.a is " + (bCopy.a == cCopy.a)); 
    } 
} 

class A implements Serializable{ 

} 

class B implements Serializable{ 
    A a; 
} 

class C implements Serializable{ 
    A a; 
} 
निम्नलिखित उत्पादन के साथ

:

b.a == c.a is true 
Case 1 - bCopy.a == cCopy.a is false 
Case 2 - bCopy.a == cCopy.a is true 
+0

"... लेकिन यह अभी भी ऑब्जेक्ट ए की एक नई प्रति है।" तो अगर मैं ऑब्जेक्ट ए कॉपी (उदा। आयु) का एक क्षेत्र बदलता हूं, तो ऑब्जेक्ट में परिवर्तन एक प्रति बीसीडीई के अंदर ऑब्जेक्ट ए (एस) में दिखाई नहीं देगी? –

+1

यह सही है। चूंकि वस्तु एक अलग ढेर पते में है। अगर उत्तर ने आपकी मदद की, तो कृपया इसे स्वीकार करें। – Anshuman

+0

उस स्थिति में, क्या आप एक तरीका सुझा सकते हैं ताकि मैं उपर्युक्त उदाहरण में सचित्र के रूप में जो हासिल करना चाहता हूं उसे पूरा कर सकूं? –

1

नहीं, सरल उत्तर यह है कि deserialized वस्तु स्मृति में एक ही उदाहरण नहीं होगा! यह इसके लिए नई मेमोरी आवंटित करेगा। http://www.javalobby.org/java/forums/t17491.html लिंक के माध्यम से भी जाएं जिसमें सिंगलटन के साथ deserialization का उपयोग कर ऑब्जेक्ट पुनर्प्राप्त करने का उदाहरण शामिल है! गहराई में readResolve() विधि के माध्यम से भी जाना, यह कुछ मामलों में सहायक होगा।

1

deserialized उदाहरण निश्चित रूप से मूल से एक विशिष्ट उदाहरण होगा, क्योंकि deserialized != original में हमेशा सत्य होगा।

deserialized उदाहरण मूल उदाहरण के बराबर हो सकता है या नहीं, जैसा कि deserialized.equals(original) में है। एक Serializable वर्ग का एक उचित कार्यान्वयन के लिए, equals शायद अक्रमांकन के बाद सच हो जाएगा, लेकिन यह एक वर्ग है जिसके लिए यह नहीं रखता है बनाने के लिए मामूली बात है:

class Pathological implements Serializable { 
    transient int value; 

    Pathological(int value) { this.value = value; } 

    @Override public int hashCode() { return value; } 

    @Override public boolean equals(Object other) { 
    if (other == this) { return true; } 
    if (other instanceof Pathological) { 
     return ((Pathological) other).value == this.value; 
    } 
    return false; 
    } 
} 

जब तक आप जब Pathological निर्माण शून्य पारित करने के लिए होता है, उदाहरण serialization/deserialization के बाद बराबर नहीं होंगे, क्योंकि value के मान को क्रमबद्ध नहीं किया जाएगा (क्योंकि यह क्षणिक है)।

1

नहीं वे स्मृति originalObj == deserilized मेमोरी में एक ही वस्तु नहीं होंगे, हालांकि originalObj.equals(deserilized) सत्य होना चाहिए।

ऑब्जेक्ट्स बी, सी, डी और ई। उन सभी को तत्काल, ऑब्जेक्ट ए था। फिर, मान लीजिए कि मैं उन सभी को क्रमबद्ध और deserialized। जब मैं deserialization के बाद ऑब्जेक्ट ए का एक क्षेत्र बदलता हूं, क्या बीसीडीई में ऑब्जेक्ट ए में ऐसे परिवर्तन को प्रतिबिंबित करने का कोई तरीका है?

तो मैं समझता हूँ कि आप सही तरीके से जवाब नहीं, संदर्भ में एक ही वस्तु एक

की ओर संकेत नहीं दिया जाएगा लेकिन अगर आप ऐसा चाहते हैं आप स्पष्ट रूप से प्रत्येक वस्तु में वस्तु एक के संदर्भ के सभी सेट कर सकते हैं बी, सी, डी और ई ऑब्जेक्ट ए

के समान उदाहरण को इंगित करने के लिए यहां दिए गए बिंदुओं को चित्रित करने के लिए एक डेमो है।

import java.io.*; 
import java.util.*; 

public class Demo { 
    public static void main(String... aArguments) { 
    List<Quark> quarks = Arrays.asList(
     new Quark("up"), new Quark("down") 
    ); 

    serialize(quarks); 
    List<Quark> recoveredQuarks = deserialize(); 

    System.out.println(quarks == recoveredQuarks);    // false 
    System.out.println(quarks.equals(recoveredQuarks));   // true 

    System.out.println(quarks.get(0) == recoveredQuarks.get(0)); // false 

    // but you can set it to the same instance 
    recoveredQuarks.set(0, quarks.get(0)); 
    System.out.println(quarks.get(0) == recoveredQuarks.get(0)); // true 

    quarks.get(0).name = "Charm"; 
    boolean b = quarks.get(0).name == recoveredQuarks.get(0).name; 
    System.out.println(b);          // true 
    } 

    static void serialize(List<Quark> quarks) { 
    try { 
     OutputStream file = new FileOutputStream("quarks.ser"); 
     OutputStream buffer = new BufferedOutputStream(file); 
     ObjectOutput output = new ObjectOutputStream(buffer); 
     output.writeObject(quarks); 
     output.close(); 
    } 
    catch(IOException ex) { ex.printStackTrace(); } 
    } 

    static List<Quark> deserialize() { 
    List<Quark> recoveredQuarks = null; 
    try { 
     InputStream file = new FileInputStream("quarks.ser"); 
     InputStream buffer = new BufferedInputStream(file); 
     ObjectInput input = new ObjectInputStream(buffer); 
     recoveredQuarks = (List<Quark>)input.readObject(); 
     input.close(); 
    } 
    catch(ClassNotFoundException ex){ } 
    catch(IOException ex){ ex.printStackTrace(); } 
    return recoveredQuarks; 
    } 
} 

class Quark implements Serializable { 
    String name; 
    Quark(String name) { 
     this.name = name; 
    } 

    @Override 
    public boolean equals(Object o) { 
     if (o != null && o instanceof Quark) { 
     return this.name.equals(((Quark)o).name); 
     } 
     return false; 
    } 
} 
3

serializing से पहले:

A originalA = ...; 
B.a == C.a == D.a == E.a == originalA 

सभी B.a, C.a, D.a और A, originalA की इसी संदर्भ को E.a बिंदु।

serializing और deserializing के बाद:

A otherA = ...; 
B.a == C.a == D.a == E.a == otherA 

सभी B.a, C.a, D.a और A, otherA की इसी संदर्भ को E.a बिंदु।

हालांकि

:

originalA != otherA 

हालांकि

originalA.equals(otherA) == true 

नोट:equals()true वापस आ जाएगी, बशर्ते यह वही ओवरराइडको लगातार जांच धारावाहिक क्षेत्रों के आधार पर समानता है। अन्यथा, यह वापसी false हो सकता है।


संपादित करें:

सबूत:

import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.Serializable; 

public class Sample { 

    static class A implements Serializable { 
     private static final long serialVersionUID = 1L; 
    } 

    static class B implements Serializable { 
     private static final long serialVersionUID = 1L; 

     A a; 
    } 

    static class C implements Serializable { 
     private static final long serialVersionUID = 1L; 

     A a; 
    } 

    public static void main(String args[]) throws IOException, ClassNotFoundException { 
     A originalA = new A(); 

     B b = new B(); 
     b.a = originalA; 

     C c = new C(); 
     c.a = originalA; 

     System.out.println("b.a == c.a is " + (b.a == c.a)); 

     FileOutputStream fout = new FileOutputStream("ser"); 
     ObjectOutputStream oos = new ObjectOutputStream(fout); 
     oos.writeObject(b); 
     oos.writeObject(c); 
     oos.close(); 
     fout.close(); 

     FileInputStream fileIn = new FileInputStream("ser"); 
     ObjectInputStream in = new ObjectInputStream(fileIn); 
     B bDeserialized = (B) in.readObject(); 
     C cDeserialized = (C) in.readObject(); 
     in.close(); 
     fileIn.close(); 

     System.out.println("bDeserialized.a == cDeserialized.a is " + (bDeserialized.a == cDeserialized.a)); 
    } 
} 
+1

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

संबंधित मुद्दे