InvalidClassException: не может привязать дескриптор не перечисления к классу перечисления - PullRequest
0 голосов
/ 11 сентября 2018

Я получаю ниже упомянутую ошибку.

java.io.InvalidClassException: cannot bind non-enum descriptor to an enum class
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:604)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1829)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1713)

Я думаю, что проблема связана с классом, который был изменен на enum когда-то назад. В связи с этим мы получаем указанное выше исключение при десериализации объекта. Есть ли способ, которым мы можем справиться с этим?

1 Ответ

0 голосов
/ 11 сентября 2018

Ответ: не совсем.

Это большая проблема с перечислениями Java. Когда вы сериализируете их напрямую, вы открываете себя для всех видов проблем с версиями.

И нет хорошего способа обойти это: как только ObjectOutputStream сталкивается с такими проблемами, сам поток находится в каком-то состоянии ошибки. Невозможно перехватить такие исключения и затем продолжить чтение из того же потока.

Другими словами: если ваш объектный поток содержит только экземпляр указанного класса enum, вы можете попробовать / перехватить и «проигнорировать» проблему. Но если вы десериализуете несколько значений, нет способа «пропустить» этот экземпляр перечисления и продолжить работу с более поздними объектами в потоке.

Мы узнали, что трудный путь. Наше решение состояло в том, чтобы ввести наш собственный класс enum-оболочки. Этот класс сериализует класс enum и константу enum как string объектов. И имеет специальный код для перестройки перечисления экземпляров при десериализации (и заботе о потенциальных конфликтах версий). И вместо (де) сериализации перечислений мы теперь сериализуем такие экземпляры оболочки перечислений.

Еще несколько деталей ... Константа перечисления может быть легко представлена ​​двумя строками: именем класса перечисления и просто константой перечисления в виде простой строки. При десериализации вы можете использовать это имя класса и строку константы перечисления в качестве входных данных для Enum.valueOf () . Вы можете либо выполнить попытку / перехватить этот вызов, и просто перехватить все ошибки, либо добавить больше смартов, предварительно проверив:

  • - известное десериализованное имя класса, которое указывает на перечислимый класс
  • если так: известна ли десериализованная константная строка перечисления и поддерживается соответствующим классом перечисления
...