Ваш тест некорректен, так как предполагает десериализацию константы перечисления более чем в одном экземпляре константы перечисления.Из §8.9 JLS ( выделение мой):
Тип перечисления не имеет экземпляров, отличных от тех, которые определены его константами перечисления.Попытка явно создать экземпляр типа enum является ошибкой во время компиляции (§15.9.1).
В дополнение к ошибке времени компиляции, еще три механизма гарантируют, что экземпляры типа enum не существуют за пределамите, которые определены его константами перечисления:
Последний метод клонирования в Enum гарантирует, что константы перечисления никогда не могут быть клонированы.
Рефлексивная реализация enumтипы запрещены.
Специальная обработка механизмом сериализации гарантирует, что повторяющиеся экземпляры никогда не будут созданы в результате десериализации.
Это означает, что установка x
на MyEnum1.INSTANCE
изменяет значение глобально, так же, как и изменение состояния "обычного" синглтона.Когда вы десериализуете константу, вы получаете тот же экземпляр, который уже существует , что означает, что он имеет текущее значение x
.
Лучшим тестом будет сериализация константы за один прогонпрограмма затем десериализуется в последующем запуске.Попробуйте следующий пример:
import java.io.*;
import java.nio.file.*;
public class Main {
public static void main(String[] args) throws Exception {
var file = Path.of(System.getProperty("user.dir")).resolve("myenum.bin");
switch (args[0].toLowerCase()) {
case "save":
var instance = MyEnum.INSTANCE;
instance.setValue(10);
try (var oos = new ObjectOutputStream(Files.newOutputStream(file))) {
oos.writeObject(instance);
}
break;
case "load":
try (var ois = new ObjectInputStream(Files.newInputStream(file))) {
System.out.println(((MyEnum) ois.readObject()).getValue());
}
break;
default:
throw new IllegalArgumentException("expected 'save' or 'load', actual = " + args[0]);
}
}
public enum MyEnum {
INSTANCE {
private int value = 5;
@Override public void setValue(int value) { this.value = value; }
@Override public int getValue() { return value; }
};
public abstract void setValue(int value);
public abstract int getValue();
}
}
Первый запуск java Main save
для сериализации константы enum в файл.Затем выполните java Main load
, который будет десериализовать константу перечисления, и выведите value
.Несмотря на сериализацию константы enum, в то время как value
был 10
, десериализованный экземпляр будет иметь value
быть 5
(начальное значение).Это строго указывает на то, что поля не сериализуются вместе с константой перечисления.
Поскольку я вижу, что мой пример кода почти такой же, как ваш, я не вижу, какая разница делает ваш фрагмент и мойведут себя по-разному ...
Ваш код создает одиночный экземпляр JVM, который устанавливает значение, сериализует перечисление, а затем десериализует перечисление.Поскольку все это происходит в одной и той же JVM, десериализованное перечисление будет тем же экземпляром, который уже существовал и изменил x
.
Мой код имеет два режима: "сохранить" и "загрузить".
- «save» создает экземпляр JVM, устанавливает
value
константы enum, затем сериализует перечисление в файл - «load» создает экземпляр JVM и десериализует константу enum изфайл.Он не изменяет
value
Два режима не могут произойти во время одного вызова программы, что означает, что для каждого режима используется другой экземпляр JVM.Поскольку это происходит в двух разных экземплярах JVM, десериализованное перечисление - это не тот экземпляр , который был сериализован.