Почему Java нуждается в интерфейсе Serializable?

Мы сильно работаем с сериализацией и должны указывать тег Serializable для каждого объекта, который мы используем, как бремя. Особенно, когда это сторонний класс, который мы не можем изменить.

Возникает вопрос: поскольку Serializable является пустым интерфейсом, а Java обеспечивает надежную сериализацию после добавления implements Serializable - почему они не сделали все сериализуемым и что это?

Что мне не хватает?

Ответ 1

Сериализация чревата подводными камнями. Автоматическая поддержка сериализации этой формы делает внутреннюю среду класса частью публичного API (поэтому javadoc предоставляет сохраняемые формы классов).

Для долговременного сохранения класс должен иметь возможность декодировать эту форму, которая ограничивает изменения, которые вы можете внести в класс. Это нарушает инкапсуляцию.

Сериализация также может привести к проблемам безопасности. Имея возможность сериализовать любой объект, к которому он имеет ссылку, класс может получить доступ к данным, которые он обычно не сможет (путем разбора результирующих байтовых данных).

Существуют и другие проблемы, такие как сериализованная форма внутренних классов, которые не были четко определены.

Создание всех классов serializable усугубит эти проблемы. Проверьте Эффективный Java Second Edition, в частности пункт 74: разумно выполнить Serializable.

Ответ 2

Я думаю, что и на Java, и на .Net люди ошибались на этот раз, было бы лучше сделать все сериализуемым по умолчанию и только нужно отметить те классы, которые не могут быть безопасно сериализованы вместо этого.

Например, в Smalltalk (язык, созданный в 70-х годах) каждый объект по умолчанию сериализуется. Я понятия не имею, почему это не так в Java, учитывая тот факт, что подавляющее большинство объектов безопасно сериализовать, а некоторые из них - нет.

Отмечая объект как сериализуемый (с интерфейсом), не волшебным образом делает этот объект сериализуемым, он был сериализуем все время, это только то, что теперь вы выразили то, что система могла найти на его, поэтому я не вижу никакой реальной причины для сериализации, как сейчас.

Я думаю, что это было либо плохое решение, сделанное дизайнерами, либо запоздалая идея, или платформа никогда не была готова выполнять сериализацию по умолчанию для всех объектов безопасно и последовательно.

Ответ 3

Не все действительно сериализуемо. Например, подключитесь к сетевому сокету. Вы можете сериализовать данные/состояние вашего объекта сокета, но суть активного соединения будет потеряна.

Ответ 4

Основная роль Serializable в Java заключается в том, чтобы по умолчанию сделать все остальные объекты несериализуемыми. Сериализация - очень опасный механизм, особенно в реализации по умолчанию. Следовательно, как и дружба на С++, она отключена по умолчанию, даже если она немного стоит сделать сериализуемыми.

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

Я должен признать, что я видел очень мало нетривиальных классов, где стандартная сериализация делает то, что я хочу. Особенно в случае сложных структур данных. Таким образом, усилия, которые вы потратили на создание класса serializble, должным образом затмевают стоимость добавления интерфейса.

Ответ 5

Для некоторых классов, особенно тех, которые представляют что-то более физическое, например File, Socket, Thread или DB, нет смысла сериализовывать экземпляры. Для многих других процесс сериализации может быть проблематичным, поскольку он разрушает ограничения уникальности или просто заставляет вас иметь дело с экземплярами разных версий класса, которые вы, возможно, не захотите.

Возможно, было бы лучше сделать все Serializable по умолчанию и сделать классы несериализуемыми через интерфейс ключевых слов или маркеров, но тогда те, кто должен использовать этот параметр, вероятно, не подумают об этом. Так оно и есть, если вам нужно реализовать Serializable, вам будет сказано об этом с помощью исключения.

Ответ 6

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

Ответ 8

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

Просто опираясь на стандартную поддержку сериализации JVM, вы подвергаете себя различным неприятным проблемам с версиями.

Уникальность, ссылки на "реальные" ресурсы, таймеры и множество других типов артефактов НЕ являются кандидатами на сериализацию.

Ответ 9

Прочитайте это, чтобы понять интерфейс Serializable и почему мы должны сделать только несколько классов Serializable, а также мы будем заботиться о том, где использовать ключевое слово transient, если мы хотим удалить несколько полей из процедуры хранения.

http://www.codingeek.com/java/io/object-streams-serialization-deserialization-java-example-serializable-interface/

Ответ 10

Хорошо, я отвечаю, что это не без оснований. И из ваших комментариев я вижу, что вы уже это узнали. Другие языки с удовольствием попробуют сериализовать все, что не прыгает на дереве, после того как вы считаете 10. Объект должен по умолчанию быть сериализуемым.

Итак, вам в основном нужно прочитать все свойства вашего стороннего класса самостоятельно. Или, если это вариант для вас: декомпилируйте, поставьте там ключевое слово damn и перекомпилируйте.

Ответ 11

В Java есть некоторые вещи, которые просто не могут быть сериализованными, потому что они являются специфичными для исполнения. Такие вещи, как потоки, потоки, время выполнения, и т.д., и даже некоторые классы GUI (которые связаны с базовой ОС) не могут сериализоваться.

Ответ 12

В то время как я согласен с пунктами, сделанными в других ответах здесь, настоящая проблема заключается в десериализации: если определение класса меняется, тогда существует реальный риск, что десериализация не будет работать. Никогда не изменяя существующие поля, это довольно важное обязательство для автора библиотеки! Поддержание совместимости API - это достаточно сложная задача.

Ответ 13

Класс, который должен сохраняться в файле или другом носителе, должен реализовать интерфейс Serializable, чтобы JVM мог разрешить сериализацию объекта класса. Почему класс Object не сериализуется, тогда ни один из классов не должен реализовывать интерфейс, ведь JVM сериализует класс только тогда, когда я использую ObjectOutputStream, что означает, что элемент управления все еще в моих руках, чтобы позволить JVM сериализоваться.

Причина, по которой класс Object не является сериализуемым по умолчанию в том, что основная проблема - версия класса. Поэтому каждый класс, который интересуется сериализацией, должен быть помечен как Serializable явно и предоставить номер версии serialVersionUID.

Если serialVersionUID не указан, мы получаем неожиданные результаты при десериализации объекта, поэтому JVM выдает InvalidClassException, если serialVersionUID не соответствует. Поэтому каждый класс должен реализовывать интерфейс Serializable и предоставлять serialVersionUID, чтобы убедиться, что класс, представленный на обоих концах, идентичен.