Почему serialVersionUID не генерируется автоматически?
Почему не serialVersionUID
автоматически генерируется? Я столкнулся с проблемой на сервере приложений, где, очевидно, кэшировался старый класс.
3 ответа
serialversionuid не генерируется автоматически, потому что это опасно. Когда установлен serialversionuid, это означает, что две версии класса совместимы в отношении сериализации.
Представьте, что у вас есть класс с именем Foo, и у него нет serialversionuid (по умолчанию), и вы сериализуете экземпляр Foo в файл. Позже вы добавите несколько новых членов в класс Foo. Если вы попытаетесь десериализовать объект Foo из файла, вы получите ошибку сериализации, сообщающую, что объекты несовместимы. Они несовместимы, это то, что вы хотите, и это по умолчанию. Они несовместимы, потому что новые члены в классе Foo не могут быть инициализированы из старого сериализованного экземпляра Foo.
Теперь вы можете сказать: "Мне все равно, в моем приложении допустимо, чтобы эти поля были неинициализированы". Если это действительно так, вы можете установить serialversionuid нового класса Foo таким же, как и старый класс Foo. Это скажет Java, что объекты совместимы в отношении сериализуемости, и Java не будет жаловаться, когда вы десериализуете старый экземпляр Foo в новый класс Foo (но новые поля по-прежнему не будут инициализированы).
Если вы впервые создаете новый класс и устанавливаете serialversionuid, вы заключаете контракт. Этот контракт гласит: "Для всех будущих версий этого класса с тем же serialversionuid я гарантирую, что они совместимы в отношении состояния и сериализации".
Если вы изменили класс и явно хотите запретить десериализацию старых версий, вы можете изменить serialversionuid на новое значение. Это вызовет исключение, если попытаться десериализовать старый объект в новый экземпляр класса.
Он генерируется автоматически на основе структуры класса. Если структура изменяется, идентификатор восстанавливается (согласно спецификации сериализации это хеш-класс).
Так что вам лучше определить явное serialVersionUID
,
Если вы используете Eclipse в качестве своей IDE, вы можете щелкнуть правой кнопкой мыши предупреждение о отсутствующем serialVersionUID, и вы получите два варианта:
1) Определите Eclipse по умолчанию, который имеет значение 1L; или же
2) Определить случайно сгенерированное длинное значение
Если вы заботитесь о версиях сериализованных объектов, вам нужно будет вручную создавать новое значение каждый раз, когда вы изменяете класс. В Javadoc для интерфейса Serializable есть что сказать о том, что происходит, если вы вообще не объявляете serialVersionUID:
Если сериализуемый класс явно не объявляет serialVersionUID, тогда среда выполнения сериализации вычислит значение serialVersionUID по умолчанию для этого класса на основе различных аспектов класса, как описано в Спецификации сериализации объектов Java(TM). Однако настоятельно рекомендуется, чтобы все сериализуемые классы явно объявляли значения serialVersionUID, так как вычисление serialVersionUID по умолчанию очень чувствительно к деталям класса, которые могут различаться в зависимости от реализаций компилятора, и, следовательно, могут привести к неожиданным исключениям InvalidClassExceptions во время десериализации. Поэтому, чтобы гарантировать согласованное значение serialVersionUID в различных реализациях Java-компилятора, сериализуемый класс должен объявить явное значение serialVersionUID.
На практике я обнаружил, что даже если вы начнете с одинакового исходного кода на двух или более компьютерах (например, извлеченных из Subversion), где serialVersionUID не определен в классе, значение, сгенерированное компилятором в классе, отличается на каждом машина, когда код скомпилирован. Это может привести к ошибкам во время разработки.
Если вы уверены, что у вас никогда не возникнет ситуация, когда у вас будут устаревшие сериализованные объекты, которые не синхронизированы с более новой версией класса (или две JVM отправят несинхронизированные сериализованные объекты друг другу, возможно, через подключение к сети или сокету), затем просто установите значение 1L для serialVersionUID и оставьте его таким навсегда.
http://download-llnw.oracle.com/javase/6/docs/api/java/io/Serializable.html