2009-12-18 8 views
1

Disons que je crée une instance de classe B, qui a une variable statique x, affectée d'une valeur de 3 dans la déclaration de classe B. Dans la méthode main(), je le fais:Quelle est la valeur des variables statiques après la désérialisation d'un objet?

B b = new B(); 
b.x = 7; //allowed to use an instance to set the static member value 

Après cela, b est sérialisé, puis désérialisé. Ensuite, la ligne suivante se produit:

System.out.println ("static: " + b.x); 

Quelle est la valeur? 7 ou 3? Je sais que les variables statiques ne sont pas sérialisées, cependant, puisqu'il n'y a qu'une seule copie du membre statique pour la classe entière, et que la valeur est définie à 7, devrait-elle être conservée après dé-sérialisation d'une instance?

+3

Pourquoi ne pas simplement l'essayer. Je suppose que cela ne vous prendra pas plus de temps que d'écrire la question. – Buhb

+1

Les statistiques statiques sont une très, très mauvaise idée, de toute façon. –

+1

@Tom, sans parler de les référencer par une instance de B plutôt que la classe elle-même (Bx) –

Répondre

8

Voilà ce qui se passe:

  1. initialiseur statique définit la valeur à 3.
  2. constructeur d'instance définit la valeur à 7.
  3. sérialisation ne connaît pas la variable statique et il est ignoré.
  4. La désérialisation ne reconnaît pas la variable statique et est ignorée.
  5. La valeur est toujours 7 (à partir de la modification qui s'est produite dans le constructeur) si le programme a été exécuté ou si le programme a été arrêté et redémarré, l'initialiseur statique l'a défini sur 3 et la dé-sérialisation n'a pas changes le.

Si vous voulez la logique que vous décrivez, vous devez ajouter une autre variable statique qui compte le nombre d'instances créées et remplacer les méthodes writeObject et readObject avec votre logique personnalisée.

7

Si vous désérialiser dans la même instance de la machine virtuelle Java, votre deuxième extrait retournera 7. En effet, la valeur de bx est réglée sur 7. Cela n'a pas changé parce que était sérialisé une instance de B et désérialisé.

Si vous sérialiser l'objet, l'arrêt de la machine virtuelle Java, mettre en place une nouvelle machine virtuelle Java et désérialiser alors l'objet (sans réglage bx nulle part autre que l'initialisation statique), la valeur de bx sera 3.

+0

+1 Même JVM ou JVM différente. Seule chose qui compte. b.x peut être n'importe quoi dans une JVM différente si l'initialiseur statique est modifié entre les exécutions. –

0

Étant donné que les initialiseurs statiques s'exécutent exactement une fois, la valeur est 7.

+0

juste pour vous faire connaître les gars ... selon Sun, la réponse est 3. – Dan

+1

Non, ce n'est pas. Pas à moins qu'il y ait quelque chose d'autre dans le code que vous n'avez pas montré. –

+1

Dan - pouvez-vous fournir un lien vers cette référence Sun? – Jared

1

Utilisez le code suivant pour sérialiser et désérialiser et objet/d'un flux en mémoire:

package com.example.serialization; 

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.Serializable; 
import junit.framework.TestCase; 


public class SerializationTest extends TestCase { 
    public void testStaticValueAfterSerialization() { 
     B b = new B(); 
     b.x = 7; //allowed to use an instance to set the static member value 

     B deserializedB = copyObject(b); 
     assertEquals("b.x should be 7 after serialization", 7, deserializedB.x); 
    } 

    private <T extends Serializable> T copyObject(final T source) { 
     if (source == null) 
       throw new IllegalArgumentException("source is null"); 
     final T copy; 
     try { 
      copy = serializationClone(source); 
      } catch (Exception e) { 
       // (optional) die gloriously! 
      throw new AssertionError("Error copying: " + source, e); 
     }  
      return copy; 
    } 

    private <T extends Serializable> T serializationClone(final T source) 
     throws IOException, ClassNotFoundException { 
    ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); 
    ObjectOutputStream outputStream = new ObjectOutputStream(byteStream); 

      // 1. serialize the object to the in-memory output stream 
     outputStream.writeObject(source); 

     ObjectInputStream inputStream = new ObjectInputStream(
       new ByteArrayInputStream(byteStream.toByteArray())); 

     // 2. deserialize the object from the in-memory input stream 
     @SuppressWarnings("unchecked") 
      final T copy = (T) inputStream.readObject(); 

     return copy; // NOPMD : v. supra 
    } 
} 

Après avoir créé cette classe, l'exécuter avec un coureur de JUnit et voir si le test passe! Si vous le souhaitez, vous pouvez écrire le résultat dans un fichier dans un cas de test. Ensuite, dans un autre cas de test, lisez le résultat d'un fichier!