Lorsque j’instancie un object d’une classe, un object est enregistré dans le segment de mémoire java. Lorsque je sauvegarde l’object en le sérialisant et que je le désérialise par la suite, ai-je bien compris que l’object aura désormais une nouvelle adresse de segment de mémoire mais restra toujours l’instance EXACT SAME de la classe.
La réponse à votre question ne peut pas être simplement un oui ou un non. Pour parsingr le concept est nécessaire. Je vous suggère de prendre un crayon et du papier et de le faire vous-même en gardant les points ci-dessous à l’esprit.
Regardez le diagramme ci-dessous pour illustrer le concept ci-dessus dans votre contexte:
Toutes les références d’object A pointent vers une entrée de segment de mémoire et si vous essayez objectB.getObjectA () == objectC.getObjectA () ou toute autre opération de ce type, vous obtiendrez la valeur true.
Cas 1 Lorsque vous enregistrez les objects séparément et que vous les désérialisez, voici ce qui se passe dans le tas:
Comme vous pouvez maintenant le constater, objectBcopy.getObjectA () == objectCcopy.getObjectA () ne renverra pas la valeur true, car les références de l’object A aux objects copiés ne sont plus les mêmes.
Cas 2 Au contraire, lorsque vous enregistrez les objects dans un seul fichier et que vous les désérialisez ultérieurement, voici ce qui se passe dans le tas:
Comme vous pouvez le constater maintenant, objectBcopy.getObjectA () == objectCcopy.getObjectA () sera désormais vrai, car les références de l’object A copie sont identiques, mais il s’agit toujours d’une nouvelle copie de l’object A.
Un programme rapide pour supporter mes déductions (cas 1 et 2):
public class Test{ public static void main (Ssortingng args[]) throws IOException, ClassNotFoundException{ A a = new A(); B b = new B(); ba = a; C c = new C(); ca = a; System.out.println("ba == ca is " + (ba == ca)); // 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; }
Avec la sortie suivante:
ba == ca is true Case 1 - bCopy.a == cCopy.a is false Case 2 - bCopy.a == cCopy.a is true
Avant de sérialiser:
A originalA = ...; Ba == Ca == Da == Ea == originalA
Tous Ba
, Ca
, Da
et Ea
la même référence de A
, originalA
.
Après la sérialisation et la désérialisation:
A otherA = ...; Ba == Ca == Da == Ea == otherA
Tous Ba
, Ca
, Da
et Ea
indiquent la même référence de A
, otherA
.
Toutefois:
originalA != otherA
bien que
originalA.equals(otherA) == true
Remarque: equals()
ne retournera true
que s’il est surchargé pour vérifier systématiquement l’ égalité en fonction des champs sérialisés. Sinon, il pourrait retourner false
.
MODIFIER:
Preuve:
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(Ssortingng args[]) throws IOException, ClassNotFoundException { A originalA = new A(); B b = new B(); ba = originalA; C c = new C(); ca = originalA; System.out.println("ba == ca is " + (ba == ca)); 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)); } }
Non, la réponse est simple: cet object désérialisé ne sera pas la même instance en mémoire! Il allouera une nouvelle mémoire pour le même. Passez également par le lien http://www.javalobby.org/java/forums/t17491.html qui contient un exemple de récupération d’object en utilisant la désérialisation avec singleton! ce sera utile dans certains cas.
L’instance désérialisée sera certainement une instance distincte de l’original, car en deserialized != original
sera toujours vrai.
L’instance désérialisée peut être égale ou non à l’instance d’origine, comme dans deserialized.equals(original)
. Pour une implémentation raisonnable d’une classe Serializable
, equals
sera probablement vrai après la désérialisation, mais il est sortingvial de créer une classe pour laquelle cela ne tient pas:
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; } }
À moins que vous ne passiez zéro lors de la construction du Pathological
, les instances ne seront pas égales après la sérialisation / désérialisation, car la valeur de value
ne sera pas sérialisée (car elle est transitoire).
Non, ils ne seront pas le même object en mémoire. originalObj == deserilized
sera faux, cependant originalObj.equals(deserilized)
devrait être vrai.
Les objects B, C, D et E. Tous, une fois instanciés, avaient l’object A. Ensuite, supposons que je les ai tous sérialisés et désérialisés. Lorsque je modifie un champ de l’object A après la désérialisation, existe-t-il un moyen de refléter un tel changement dans le ou les objects A dans BCDE?
Si je vous ai bien compris, la réponse est non, les références ne désigneront pas le même object.
Toutefois, si vous le souhaitez, vous pouvez définir explicitement toutes les références de l’object A dans chaque object B, C, D et E pour qu’elles pointent vers la même instance de l’object A.
Voici une démo pour illustrer les points soulevés.
import java.io.*; import java.util.*; public class Demo { public static void main(Ssortingng... aArguments) { List quarks = Arrays.asList( new Quark("up"), new Quark("down") ); serialize(quarks); List 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 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 deserialize() { List recoveredQuarks = null; try { InputStream file = new FileInputStream("quarks.ser"); InputStream buffer = new BufferedInputStream(file); ObjectInput input = new ObjectInputStream(buffer); recoveredQuarks = (List )input.readObject(); input.close(); } catch(ClassNotFoundException ex){ } catch(IOException ex){ ex.printStackTrace(); } return recoveredQuarks; } } class Quark implements Serializable { Ssortingng name; Quark(Ssortingng 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; } }