Pergunta

Digamos que eu crie uma instância da classe B, que possui uma variável estática x, atribuída com valor 3 na declaração da classe B.No método main(), eu faço isso:

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

Depois disso, b é serializado e então desserializado.Então ocorre a seguinte linha:

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

Qual é o valor?7 ou 3?

Eu sei que variáveis ​​estáticas não são serializadas, entretanto, como há apenas uma cópia do membro estático para toda a classe e o valor está definido como 7, ele deve ser preservado após desserializar uma instância?

Foi útil?

Solução

Aqui está o que acontece:

  1. O inicializador estático define o valor como 3.
  2. O construtor da instância define o valor como 7.
  3. A serialização não tem conhecimento da variável estática e é ignorada.
  4. A desserialização não tem conhecimento da variável estática e é ignorada.
  5. O valor ainda é 7 (da mudança que ocorreu no construtor) se o programa esteve em execução o tempo todo, ou se o programa foi encerrado e reiniciado, o inicializador estático o terá definido como 3 e a desserialização não o alterou.

Se você quiser a lógica descrita, precisará adicionar outra variável estática que conte o número de instâncias criadas e substitua a writeObject e readObject métodos com sua lógica personalizada.

Outras dicas

Se você desserializá-lo na mesma instância da JVM, seu segundo trecho retornará 7.Isso ocorre porque o valor de bx está definido como 7.Isso não mudou porque uma instância de B foi serializado e desserializado.

Se você serializar o objeto, encerrar a JVM, abrir uma nova JVM e, em seguida, desserializar o objeto (sem definir b.x em qualquer lugar que não seja a inicialização estática), o valor de b.x será 3.

Use o código a seguir para serializar e desserializar e objetar para/de um fluxo na memória:

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
    }
}

Depois de criar essa classe, execute-a com um executor JUnit e veja se o teste passa!Se desejar, você pode gravar o resultado em um arquivo em um caso de teste.Então, em outro caso de teste, leia o resultado de um arquivo!

Como os inicializadores estáticos são executados exatamente uma vez, o valor é 7.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top