Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Десериализация: зачем нужен пустой конструктор? 
V
    Опции темы
Dims
Дата 2.3.2009, 12:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 4
Всего: 11



При десериализации объекта, система ругается InvalidClassException, no valid constructor.

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

А зачем? Получается, я должен всем классам и классам членов добавить implements Serializable и пустые конструкторы. Как-то стрёмно. Что я при этом должен обеспечить логически? Может ли быть так, что я всё это сделаю, а сериализация будет работать неправильно?
PM MAIL   Вверх
gambit
Дата 2.3.2009, 13:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***
Награды: 1



Профиль
Группа: Комодератор
Сообщений: 1359
Регистрация: 25.6.2006
Где: я?

Репутация: нет
Всего: 40



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

Добавлено через 1 минуту и 15 секунд
блин, я разделом ошибся.  smile 

но может и для java это справедливо?
PM MAIL ICQ Skype   Вверх
Platon
Дата 2.3.2009, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



JavaBeans
Цитата

Класс должен иметь public конструктор без параметров. Такой конструктор позволяет инструментам создать объект без дополнительных сложностей с параметрами.

PM MAIL ICQ   Вверх
dorogoyIV
Дата 2.3.2009, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1503
Регистрация: 26.3.2007

Репутация: 3
Всего: 46



по моему компилятор должен сам создавать конструктор дефолтный - по крайней мере так написано у меня в учебнике, т.е. конструктор у класса есть всегда, даже если сам его не писал
PM MAIL   Вверх
powerOn
Дата 2.3.2009, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Цитата(dorogoyIV @  2.3.2009,  14:30 Найти цитируемый пост)
по моему компилятор должен сам создавать конструктор дефолтный 


только если нет других конструкторов. Стоит написать какой-либо с параметрами, так дефолтный не будет создан.


--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
COVD
Дата 2.3.2009, 16:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 17
Всего: 43



Цитата

А зачем?

Наверное, это позволяет восстанавливать сериализованный обьект из потока, т.е. начать не дожидаясь получения всего обьекта. Сериализованный обьект начинается с описания класса. Читается описание и создается пустой обьект. Для этого класс и должен иметь пустой конструктор. Потом идут параметры, если есть. Они последовательно читаются и вставляются в созданный обьект (через сеттеры, ведь наверное речь идет о javabean). Вторая причина - при сериализации пустые параметры ( параметр = null ) просто не пишутся в поток, т.е. минимизируется размер сериализованного обьекта.

Это сообщение отредактировал(а) COVD - 2.3.2009, 16:47
PM MAIL   Вверх
lemonade
Дата 2.3.2009, 16:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 7.12.2006
Где: Беларусь, Минск

Репутация: нет
Всего: 2



Dims
еще жедательно добавить serialVersionUID поле
Цитата

The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long:

 ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
 
If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java™ Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members.

PM MAIL ICQ Skype   Вверх
Dims
Дата 2.3.2009, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 4
Всего: 11



Нет, у меня класс не следует спецификациям бинов. Получается, его нельзя сериализовать?

Мне кажется, что можно. И отсюда вопрос. Вот у меня класс с приватным параметром. Десериализатор ведь как-то умудряется его прочитать из файла и присвоить, хотя сеттера и геттера у меня к нему может и не быть. Так почему же ему нужен конструктор, чтобы создать объект?

Вопрос можно сформулировать более общо: достаточно ли удовлетворить формальным требованиям компиллятора и джавамашины к сериализуемым объектам, чтобы всё работало правильно?

Иными словами, вот у меня есть класс, который нормально, без ошибок, сериализуется и десериализуется. Могу ли я быть уверен, что всё работает правильно, или я должен ещё за чем-то проследить?

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

А в чём моя ответственность при сериализации? Какие тут могут быть логические ошибки?

Добавлено через 5 минут и 8 секунд
Допустим, у меня класс, который внутри содержит массив. Параметр конструктора --это число элементов в этом массиве. Есть дефолтный конструктор, который устанавливает число элементов в 100. 

Допустим, у меня был объект, в котором было 42 элемента. Я его сериализовал. 

Получается, при десериализации будет вызван дефолтный конструктор, то есть, создадутся 100 элементов. Затем из файла будет прочитан массив из 42 элементов.

В лучшем случае 100 элементный массив просто пойдёт в мусорку, то есть, это лишняя работа. А в худшем - возникнет какая-то ошибка.
PM MAIL   Вверх
COVD
Дата 2.3.2009, 16:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 17
Всего: 43



Цитата

Иными словами, вот у меня есть класс, который нормально, без ошибок, сериализуется и десериализуется. Могу ли я быть уверен.

если без ошибок, то да. Изначально то вопрос был отчего требование пустого конструктора. Как я уже добавил выше, наверное, основная причина в том, что неопределенные параметры обьекта не сериализуются в целях минимизации размера. 
PM MAIL   Вверх
Dims
Дата 2.3.2009, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 4
Всего: 11



Ха, я сделал такой конструктор

Код

public Context() {
      this(1);
   }


и всё равно возникает та же ошибка!

Добавлено через 4 минуты и 22 секунды
Цитата(COVD @  2.3.2009,  16:54 Найти цитируемый пост)
наверное, основная причина в том, что неопределенные параметры обьекта не сериализуются в целях минимизации размера. 

Но это не объясняет, зачем нужен конструктор. Что мешает десериализатору просто прочитать из файла все поля и тупо присвоить их членам? А пропущенные пусть ставит в null. 

Конструктор-то как этому поможет/помешает?

Добавлено через 6 минут и 37 секунд
Блин, вот оно что: http://www.jguru.com/faq/view.jsp?EID=251942

Добавлено через 8 минут и 7 секунд
То есть, конструктор без параметров должен быть у того НАДкласса сериализуемого класса, который сам не является сериализуемым.
PM MAIL   Вверх
COVD
Дата 2.3.2009, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 17
Всего: 43



Цитата

Но это не объясняет, зачем нужен конструктор. Что мешает десериализатору просто прочитать из файла все поля и тупо присвоить их членам? А пропущенные пусть ставит в null. 

Вы логику разработчиков десериализатора хотите понять? Мне кажется она проста и надежна - делай раз (создай пустой обьект), делай два (если есть параметр, прочитай и засунь в обьект). Пункт два выполняется в цикле. Сериализованный обьект - это последовательность байт, которые и обрабатываются последовательно. Очевидно, именно последовательно и будет "тупо", а не "прочитать ВСЕ" и "тупо присвоить". А требование наличия пустого конструктора не выглядит обременительным.

Это сообщение отредактировал(а) COVD - 2.3.2009, 17:28
PM MAIL   Вверх
LSD
Дата 2.3.2009, 17:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15717
Регистрация: 24.3.2004
Где: Dublin

Репутация: 209
Всего: 537



Цитата(Dims @  2.3.2009,  16:57 Найти цитируемый пост)
Что мешает десериализатору просто прочитать из файла все поля и тупо присвоить их членам?

Необходимость того чтобы объект был корректно создан. Когда ты объявляешь объект сериализуемым ты закладываешь (по крайней мере должен) возможность того что он будет создан без вызова конструктора (тогда логика инициализации закладывается в defaultReadObject()). А вот не сериализуемый суперкласс, такого метода не имеет и потому для него вызов конструктора - обязателен.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Vitaly333
Дата 2.3.2009, 18:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 6.11.2006
Где: Volgograd

Репутация: 2
Всего: 2




Цитата

То есть, конструктор без параметров должен быть у того НАДкласса сериализуемого класса, который сам не является сериализуемым. 


Да ,здесь всё дело именно в этом. Допустим у вас есть такой класс c несколькими конструкторами и он не реализует Serializable:

Код

Class Parent {

private int a,b;

public Parent(int a, int b){
  this.a = a;
  this.b = b;
}

public Parent(int a){
  this.a = a;
  b = a;
}


}


И есть класс его наследник:

Код


Class Chield extends Parent implements Serializable{

private c;

public Chield(int a,int b,int c){
 super(a,b);
 this.c = c;
}





Допустим вы  породили некий объект, от класса Chield и хотите его сериализовать. Так как  суперкласс не реализует Serializable, то поля a и b, унаследованные от него не будут сериализованы. Но при диссериализации их же нужно как - то инициализировать. Единственная возможность - вызвать конструктор суперкласса! Но у суперкласса определенно 2 конструктора. Возникает вопрос - а какой из них вызывать и какие значения ему передовать??? Поэтому и было принято решение , что при сериализации в суперклассе (который не реализует Serializable) обязательно должен быть определен конструктор по умолчанию(без параметров), который и осуществляет эту инициализацию.
PM MAIL   Вверх
Dims
Дата 2.3.2009, 18:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 4
Всего: 11



Цитата(COVD @  2.3.2009,  17:10 Найти цитируемый пост)
Вы логику разработчиков десериализатора хотите понять? Мне кажется она проста и надежна - делай раз (создай пустой обьект)

Я нашёл ссылку. В ней написано, что это НЕ ТАК. Конструктор без параметров не нужен, что подтверждается тем, что ошибка сохранилась тогда, когда я такой конструктор создал.

Цитата(Vitaly333 @  2.3.2009,  18:35 Найти цитируемый пост)
Так как  суперкласс не реализует Serializable, то поля a и b, унаследованные от него не будут сериализованы.

Вообще-то, следования тут нет. Разработчики могли бы сделать так, чтобы это просто было запрещено. То есть, они могли потребовать, чтобы объекты Serializable обязательно имели в предках тоже Serializable, либо не имели предков вовсе (примерно так, как сделали с Cloneable). 

Но они поступили по-иному, они разрешили сериализовать объекты с несериализуемыми предками при условии, что предок имеет конструктор по умолчанию, то есть, осмысленно существование "пустого" объекта. 

Цитата(Vitaly333 @  2.3.2009,  18:35 Найти цитируемый пост)
Поэтому и было принято решение , что при сериализации в суперклассе (который не реализует Serializable) обязательно должен быть определен конструктор по умолчанию(без параметров), который и осуществляет эту инициализацию. 

Вот в таком виде это уже кажется разумным. Изначально мне это было непонятно.

Добавлено через 2 минуты и 43 секунды
Цитата(LSD @  2.3.2009,  17:26 Найти цитируемый пост)
А вот не сериализуемый суперкласс, такого метода не имеет и потому для него вызов конструктора - обязателен. 

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

Мне кажется, многие из тех, кто мне отвечал, тоже так думали ;)

PM MAIL   Вверх
gosnis
Дата 2.3.2009, 19:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 87
Регистрация: 16.5.2007
Где: Тель Авив, Израил ь

Репутация: нет
Всего: 2



Читаем javadoc интерфэйса Serializable:
Цитата

To allow subtypes of non-serializable classes to be serialized, the subtype may assume responsibility for saving and restoring the state of the supertype's public, protected, and (if accessible) package fields. The subtype may assume this responsibility only if the class it extends has an accessible no-arg constructor to initialize the class's state. It is an error to declare a class Serializable if this is not the case. The error will be detected at runtime.

То есть, у вас есть Base класс (несериализируемый) и его наследник - Derived класс. Что бы сделать Derived класс сериализируемым, в Base класс должен быть конструктор без аргументов (Base()) иначе получите ошибку во время запуска программы (runtime).
PM MAIL ICQ Skype MSN   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0984 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.