Как завершить создание объекта после того, как я его десериализую [дублировать]

Добавление случая, когда имя класса для объекта, используемого в структуре сущности, такое же, как имя класса для файла с кодировкой веб-формы.

Предположим, у вас есть веб-форма Contact.aspx, чей класс codebehind Свяжитесь с вами, и у вас есть имя объекта Contact.

Затем следующий код вызовет исключение NullReferenceException при вызове context.SaveChanges ()

Contact contact = new Contact { Name = "Abhinav"};
var context = new DataContext();
context.Contacts.Add(contact);
context.SaveChanges(); // NullReferenceException at this line

Ради полноты класса DataContext

public class DataContext : DbContext 
{
    public DbSet Contacts {get; set;}
}

и класс сущности контакта. Иногда классы сущностей являются частичными классами, так что вы можете распространять их и в других файлах.

public partial class Contact 
{
    public string Name {get; set;}
}

Ошибка возникает, когда оба класса entity и codebehind находятся в одном и том же пространстве имен. Чтобы исправить это, переименуйте класс сущности или класс codebehind для Contact.aspx.

Причина. Я все еще не уверен в причине. Но всякий раз, когда какой-либо из классов сущностей расширяет System.Web.UI.Page, возникает эта ошибка.

Для обсуждения рассмотрим NullReferenceException в DbContext.saveChanges ()

3
задан Jérôme Verstrynge 12 August 2011 в 02:27
поделиться

5 ответов

О readObject()/writeObject() является приватным, вот сделка: если ваш класс Bar расширяет некоторый класс Foo; Foo также реализует readObject()/writeObject(), а Bar также реализует readObject()/writeObject().

Теперь, когда объект Bar сериализуется или десериализуется, JVM необходимо автоматически вызвать readObject()/writeObject() для Foo и Bar (т.е. без необходимости для вызова этих методов суперкласса). Однако, если эти методы не являются частными, он становится переопределяющим методом, и JVM больше не может вызывать методы суперкласса для объекта подкласса.

Следовательно, они должны быть частными!

6
ответ дан shrini1000 4 September 2018 в 08:19
поделиться

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

Изменить: если вы хотите, чтобы подклассы могли изменять поведение, сделайте метод protected ... это приемлемым.

1
ответ дан ColinD 4 September 2018 в 08:19
поделиться

Чтобы ваш метод вызывался objectInputStream.readObject (), вы должны объявить его приватным:

private void readObject(ObjectInputStream objectInputStream)

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

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

objectInputStream.defaultReadObject();

... вопреки другим сообщениям, которые я прочитал в Интернете. То же самое относится и к методам writeObject.

1
ответ дан Paul Jackson 4 September 2018 в 08:19
поделиться

В современных реализациях Java (по крайней мере, с JDK с 6 по 10) классы ObjectInputStream и ObjectOutputStream будут распознавать только методы readObject, readObjectNoData и writeObject, если они объявлены как private и НЕ static.

(я не мог найти это явно в любой документации, но ограничение явно реализовано в коде.)

Итак, независимо от того, это хорошая идея или нет, FindBugs прав, указывая, что не-частный readObject метод является ошибкой. Он не будет использоваться.

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

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

Проблема с попыткой заставить других людей реализовать подклассы определенным образом, так это то, что они могут использовать -case, что требует , чтобы они делали что-то по-другому ... по причинам, которые вы не в состоянии понять. Это лучшая идея оставить будущих разработчиков свободу делать то, что они хотят, и позволить им взять на себя ответственность за последствия.

3
ответ дан Stephen C 4 September 2018 в 08:19
поделиться

Я не уверен, почему findbugs думает, что это ошибка, но я могу догадаться по двум возможным причинам. Выполнение инкапсуляции public breaks readObject, поскольку код вызова имеет видимость во внутренней структуре вашего класса. Кроме того, объявляя его общедоступным, вы вынуждаете все производные классы объявлять readObject как общедоступные. Поэтому, если класс не является окончательным, вы меняете контракт на сериализацию.

Я думал, что findbugs могут служить основанием для большинства его сообщений. Есть ли что-нибудь об этом?

1
ответ дан Ted Hopp 4 September 2018 в 08:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: