?

Log in

No account? Create an account
Задача - В мире нет ничего простого — ЖЖ
Июль 19, 2011
12:56 am

[Ссылка]

Previous Entry Поделиться Next Entry
Задача
Запись будет интересна только программистам.

С этой ситуацией я столкнулся в ходе работы и довольно долго ломал над ней голову. Возможно, для искушенного Java-программиста она окажется тривиальной, но мне, когда я понял, в чем дело, ситуация показалась любопытной - в частности и тем, что проблема хорошо формулируется в форме обобщенной задачи.
Итак: имеется несериализуемый класс Java. Первый оператор в его коде - объявление нестатического приватного поля произвольного (т. е. не имеющего значения для задачи) типа. Поле инициализируется сразу при объявлении значением, которое заведомо не null и (для поля примитивного типа) не 0 - скажем, вызовом соответствующего конструктора или литералом, если это возможно.
Компиляция происходит без проблем, но в ходе выполнения при единственное во всем коде обращение к этому полю оказывается, что оно не проинициализировано: скажем, попытка вызвать какой-то метод этого поля, если оно объектное, вызывает NullPointerException. В какой ситуации такое должно произойти?
Решение прячу под кат и к тому же - для желающих попредлагать варианты, не глядя на ответ, - пишу белым по белому; для прочтения текст нужно выделить.
Суть такова: у нашего класса имеется абстрактный суперкласс. У суперкласса определен конструктор, который, разумеется, вызывается конструктором нашего класса. Конструктор родителя вызывает метод, который в родителе определен как абстрактный, а реализован именно в нашем классе. И именно в этой реализации абстрактного находится то самое единственное обращение к полю. При попытке сконструировать экземпляр нашего класса и оказывается, что поле ведет себя как неинициализированное.
Дело, насколько я понимаю, в том, что методу самого нашего класса доступ к полям, разумеется, открыт, но вот его собственные, не унаследованные поля инициализированы быть еще не могут, т. к. собственно экземпляр класса еще не начал создаваться.
Любопытно: как обрабатывается аналогичная ситуация в других подобных языках? Кто может, попробуйте проверить.

Tags: , , ,

(4 комментария | Оставить комментарий)

Comments
 
[User Picture]
From:whitelynx
Date:Июль 19, 2011 08:59 am
(Link)
Моя версия (решение пока не прочел) - обращение к полю происходит в процессе инициализации другого поля, которое было объявлено раньше. Таким образом получается, что в момент обращения к полю оно еще не инициализировано.
[User Picture]
From:bukky_boogwin
Date:Июль 19, 2011 09:17 am
(Link)
Нет, не настолько просто :) Если инициализация того, другого поля происходит тоже при его объявлении, то получается ошибка компиляции, а если позже, уже после инициализации нашего поля, то все нормально инициализируется и работает.
[User Picture]
From:whitelynx
Date:Июль 19, 2011 09:41 am
(Link)
Да, я уже прочел, у тебя все хитрее. Но в моем случае тоже может быть схожая проблема без ошибки компиляции. Ну например
class A {
private int i1 = f();
private String s2 = "abc";

public int f() {
return s2.length() + 1;
}
}
[User Picture]
From:bukky_boogwin
Date:Июль 19, 2011 10:26 am
(Link)
Хммм... да, ты прав, получается то же самое. Не уследил :) Надо будет как-то сузить условие... скажем, объявление нашего поля можно по условию сделать первым оператором в коде класса.
Разработано LiveJournal.com