Использование прямого доступа к полю вместо геттеров в конструкторе копирования приводит к исключению нулевого указателя - PullRequest
0 голосов
/ 15 января 2019

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

У меня есть куча сущностей. Они организованы как дерево. Связанные объекты выбираются с нетерпением.

Я использую Hibernate, Lombok и IntelliJ для отладчика.

Когда я беру одно из деревьев сущностей за корень, я получаю дерево объектов. Давайте назовем это «оригинал». По какой-то причине, связанной с бизнес-требованиями, мне нужно скопировать его (назовем это «копией»). Я делаю это используя конструктор копирования. Сначала я написал версию конструктора копирования с использованием прямого доступа к полю.

 this.someField= original.someField

Это не сработало. Когда я проверил отладчик, я увидел, что original.someField (как и другие поля) всегда были нулевыми.

enter image description here

Тем не менее, он работает с использованием геттеров.

 this.setSomeField(original.getSomeField())

В отладчике я вижу, что поля «установлены» в original.handler.target. (Я понятия не имею, что такое handler.target).

enter image description here

Может ли кто-нибудь объяснить мне, почему прямой доступ к полю не работает?
(Я спрашиваю о технической причине, а не о философской, такой как «всегда следует использовать добытчики» и т. Д.).

Я также был бы рад узнать, что такое "handler.target".

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 15 января 2019

То, с чем вы столкнулись, вовсе не является проблемой Java 101. Hibernate имеет функцию, называемую отложенной загрузкой, которая позволяет платформе откладывать загрузку (потенциально тяжелого) объекта на более поздний момент времени, , только когда это необходимо . Это удобно, например, когда вы загружаете объект account только для проверки флага active, но абсолютно не требуется вся история входа, полученная с этой учетной записью.

Теперь часть "только тогда, когда это необходимо" : геттеры.

Hibernate знает, что вам нужен этот лениво загружаемый объект, когда вы вызываете метод получения родительского объекта в графе объектов. Пока вы не сделаете это, лениво упомянутый объект остается нулевым Прямой доступ к переменным обходит проксилогику, которая выполняет этот «трюк», и именно так вы получаете неожиданные нулевые значения. когда к полю обращаются через его получатель, включается прокси-код, происходит загрузка, и вы возвращаете свой объект.

handler/target/etc - это просто дополнительные ссылки, которые вам нужны для получения прокси. (ваш account больше не будет иметь прямую переменную accounthistory, но вместо этого будет accounthistory_proxy, который в свою очередь будет иметь accounthistory_real)

0 голосов
/ 15 января 2019

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

...