¿Cuál es el valor de las variables estáticas después de deserializar un objeto?
-
20-09-2019 - |
Pregunta
Digamos que puedo crear una instancia de la clase B, que tiene una x variable estática, asignado con un valor de 3 en la declaración de clase B. En el método main (), hago esto:
B b = new B();
b.x = 7; //allowed to use an instance to set the static member value
Después de esto, b es serializado y luego-serializado DE. Después, la línea siguiente se produce:
System.out.println ("static: " + b.x);
¿Cuál es el valor? 7 o 3?
Sé que las variables estáticas no son serializados, sin embargo, ya que sólo hay una copia del miembro estático para toda la clase, y el valor se establece en 7, si se conserva después de-serializar una instancia?
Solución
Esto es lo que sucede:
- inicializador estático establece el valor a 3.
- constructor Instancia establece el valor a 7.
- La serialización es consciente de la variable estática y se ignora.
- De-serialización no es consciente de la variable estática y se ignoran.
- El valor es todavía 7 (a partir del cambio que se produjo en el constructor) si el programa ha estado funcionando todo el tiempo, o si el programa fue apagado y reiniciado, el inicializador estático habrá establecido a 3 y de-serialización no lo hizo cambiarlo.
Si desea que la lógica que usted describe, es necesario añadir otra variable estática que cuenta el número de instancias creadas y anular los métodos writeObject
y readObject
con su lógica personalizada.
Otros consejos
Si deserializar en la misma instancia de la JVM, el segundo fragmento volverá 7. Esto se debe a que el valor de BX se establece en 7. Eso no ha cambiado porque una instancia de B fue serializado y deserializado.
Si serializar el objeto, el apagado de la máquina virtual Java, que aparezca una nueva máquina virtual Java, y luego deserializar el objeto (sin establecer b.x en cualquier lugar que no sea la inicialización estática), el valor de b.x será 3.
Utilice el siguiente código para serializar y deserializar y oponerse a / de una corriente en memoria:
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
}
}
Después de la creación de esa clase, lo hace funcionar con un corredor de JUnit y ver si pasa la prueba! Si lo desea, puede escribir el resultado en un archivo en un caso de prueba. A continuación, en otro caso de prueba, lea el resultado de un archivo!
Desde inicializadores estáticos se ejecutan exactamente una vez, el valor es 7
.