Десериализация при перезапуске Java-программы

#java #deserialization

#java #десериализация

Вопрос:

Я написал два простых тестовых примера Junit, один для serailize, а другой для десериализации. Когда я запустил два тестовых примера одновременно, десериализация сработала и выдала мне правильный вывод сохраненного значения, равного 20. НО когда я запускал тестовые примеры один за другим (или вы можете запустить программу и сериализовать, а затем запустить программу просто для десериализации), я получаю другой хэш-код и другое сохраненное значение, равное 10.

 public class SerializedSingletonClass implements Serializable{

/**
 * 
 */
private static final long serialVersionUID = 10L;

private int value = 10;

private static class SingletonHolder{
    private static SerializedSingletonClass ref = new SerializedSingletonClass();
}

public static SerializedSingletonClass getObject() {
    return SingletonHolder.ref;
}

public Object readResolve() {
    return SingletonHolder.ref;
}

public int getValue() {
    return value;
}

public void setValue(int value) {
    this.value = value;
}   
}
  

Мои тестовые примеры должны запускаться по одному (например, вы начинаете сериализацию, а затем снова начинаете десериализацию)

 public void breakingSingleton_of_SerializedSingletonClass_with_serialization() throws FileNotFoundException, IOException, ClassNotFoundException {

    ObjectOutputStream oos = new ObjectOutputStream(
            new FileOutputStream(
                    "serialized.ser"));
    SerializedSingletonClass ref = SerializedSingletonClass.getObject();
    ref.setValue(20);
    oos.writeObject(ref);
    System.out.println(ref.hashCode());
    oos.close();
    }
  

Десериализовать тестовый пример

 @Test
public void test() throws FileNotFoundException, IOException, ClassNotFoundException {

    ObjectInputStream ois = new ObjectInputStream(
            new FileInputStream(
                    "serialized.ser"));

    SerializedSingletonClass ref2 = (SerializedSingletonClass) ois.readObject();
    ois.close();
    System.out.println(ref2.hashCode());
    System.out.println(ref2.getValue());

}
  

Вывод: я получаю другой хэш-код и значение, равное 10.

Вопрос: Как правильно десериализовать?

Комментарии:

1. Вы не реализуете стабильное переопределение hashCode(), поэтому Java использует значение по умолчанию, которое основано на местоположении объекта при его создании ( srvaroa.github.io/jvm/java/openjdk/biased-locking/2017/01/30 /… ). Если вам нужен стабильный хэш-код, вы должны определить его самостоятельно.

2. Спасибо за понимание hascode. и для десериализации я нашел виновника. Проблема заключалась в readResolve(), я узнал, что когда вы предоставляете readResolve (), он действует на экземпляр, только что созданный с помощью сериализации. Итак, в моем случае, я подозреваю, что, поскольку при втором запуске не было создано ни одного экземпляра, он создает один и присваивает значение 10, а затем десериализует его значением 10. Удаление readResolve() решило проблему.