Ответы на вопросы по ревью 4. Java io. Ключевым понятием здесь является понятие потока
Скачать 1.93 Mb.
|
Сериализуемыми могут быть только классы, реализующие сериализуемостьАналогично клонируемому интерфейсу для Клонирование Java в сериализации у нас есть один сериализуемый интерфейс маркера, который работает как флаг для JVM. Любой класс, который реализует Сериализуемый интерфейс напрямую или через своего родителя, может быть сериализован, а классы, которые не реализуют |/Сериализуемый не может быть сериализован. Процесс сериализации Java по умолчанию полностью рекурсивен, поэтому всякий раз, когда мы пытаемся сериализовать один объект, процесс сериализации пытается сериализовать все поля (примитивные и ссылочные) с помощью нашего класса (кроме static и переходные поля). Когда класс реализует Сериализуемый интерфейс, все его подклассы также сериализуемы. Но когда объект имеет ссылку на другой объект, эти объекты должны реализовывать Сериализуемый интерфейс отдельно. Если в нашем классе есть хотя бы одна ссылка на не Сериализуемый класс, то JVM выдаст Исключение NotSerializableException . Почему Сериализуемый не реализуется объектом?Теперь возникает вопрос, если сериализация является очень базовой функциональностью и любой класс, который не реализует Сериализуемый , не может быть сериализован, то почему Сериализуемый не реализуется самим Объектом ?, Таким образом, все наши объекты могут быть сериализованы по умолчанию. Класс Объект не реализует Сериализуемый интерфейс, потому что мы, возможно, не захотим сериализовать все объекты, например, сериализация потока не имеет никакого смысла, потому что поток, запущенный в моей JVM, будет использовать память моей системы, сохранять ее и пытаться запустить ее в вашей JVM, не будет иметь смысла. Переходные и статические поля не сериализуютсяЕсли мы хотим сериализовать один объект, но не хотим сериализовать некоторые конкретные поля, мы можем пометить эти поля как временные . Все статические поля принадлежат классу, а не объекту, и процесс сериализации сериализует объект, поэтому статические поля не могут быть сериализованы. Сериализация не заботится о модификаторах доступа к полю, таких как private . Все нестационарные и нестатические поля считаются частью постоянного состояния объекта и могут быть сериализованы. Мы можем присваивать значения конечным полям только в конструкторах, и процесс сериализации не вызывает никакого конструктора, но все же он может присваивать значения конечным полям. Что такое serialVersionUID и почему мы должны его объявлять?Предположим, у нас есть класс, и мы сериализовали его объект в файл на диске, и из-за некоторых новых требований мы добавили/удалили одно поле из нашего класса. Теперь, если мы попытаемся десериализовать уже сериализованный объект, мы получим Исключение InvalidClassException , почему? Мы получаем это, потому что по умолчанию JVM связывает номер версии с каждым сериализуемым классом для управления версиями класса. Он используется для проверки того, что сериализованные и десериализованные объекты имеют одинаковые атрибуты и, следовательно, совместимы с десериализацией. Номер версии сохраняется в поле с именем serialVersionUID . Если сериализуемый класс не объявляет serialVersionUID , JVM автоматически создаст его во время выполнения. Если мы изменим структуру нашего класса, например, удалим/добавим поля, номер версии также изменится, и в соответствии с JVM наш класс не совместим с версией класса сериализованного объекта. Вот почему мы получаем исключение, но если вы действительно думаете об этом, почему оно должно быть выброшено только потому, что я добавил поле? Нельзя ли просто установить для поля значение по умолчанию, а затем записать его в следующий раз? Да, это можно сделать, указав поле serialVersionUID вручную и убедившись, что оно всегда одно и то же. Настоятельно рекомендуется, чтобы каждый сериализуемый класс объявлял свой serialVersionUID , поскольку созданный класс зависит от компилятора и, следовательно, может привести к неожиданным Недопустимые исключения классов. Вы можете использовать утилиту, которая поставляется с дистрибутивом JDK, называемую serialver , чтобы посмотреть, каким будет этот код по умолчанию (по умолчанию это просто хэш-код объекта). |