在复制构造函数中使用直接字段访问而不是 getter 会导致空指针异常

Using direct field access instead of getters in a copy constructor leads to null pointer exception

它必须是 Java 101 但我不明白为什么我不能使用直接字段访问以及为什么我被迫在复制构造函数中使用 getter。

我有一堆实体。它们像树一样组织起来。链接的实体被急切地获取。

我正在使用 Hibernate、Lombok 和 IntelliJ 作为调试器。

当我从根部拉出一棵实体树时,我得到了一棵对象树。我们称它为 "the original"。由于某些与业务需求相关的原因,我需要复制它(我们称其为 "the copy")。我使用复制构造函数来做到这一点。 我首先使用直接字段访问编写了一个版本的复制构造函数。

 this.someField= original.someField

没用。当我检查调试器时,我发现 original.someField(以及其他字段)始终为空。

不过,它可以使用吸气剂。

 this.setSomeField(original.getSomeField())

在调试器中,我可以看到 original.handler.target 中的字段是 "set"。 (我不知道 handler.target 是什么)。

有人可以向我解释为什么直接字段访问不起作用吗?
(我问的是技术原因,而不是 "you should always use getters" 等哲学原因)。

我也很高兴知道什么是 "handler.target"。

提前致谢。

根据我的理解,您正在获取代理对象,一旦您调用 getter 方法,您将获得实际的 object.Please 您能否在调用 gettter 方法之后检查仍然是对象的字段是空的?尝试使用。调用 getter 后的运算符,我认为字段中的值应该来。

你遇到的根本不是Java101的问题。 Hibernate 有一个称为延迟加载的功能,它允许框架将(可能很重的)对象的加载延迟到稍后的时间点,仅在需要时。例如,当您加载一个 account 对象只是为了检查 active 标志时,这会很方便,但绝对不需要使用该帐户获取所有登录历史记录。

现在 "only when it is needed" 部分 :getters.

当您在对象图中的父对象上调用 getter 时,Hibernate 知道您确实需要可延迟加载的对象。在您这样做之前,延迟引用的对象将保持为空。直接变量访问绕过执行此 "trick" 的代理逻辑,这就是您获得意外空值的方式。当通过 getter 访问该字段时,代理代码启动,加载发生,然后您取回对象。

handler/target/etc 只是由于代理而需要 hvae 的额外参考。 (你的 account 将不再有一个直接的 accounthistory 变量,而是一个 accounthistory_proxy,它又将有一个 accounthistory_real