它一定是 Java 101,但我不明白为什么我不能使用直接字段访问以及为什么我被迫在复制构造函数中使用 getter。
我有很多实体。它们像树一样组织起来。急切地获取链接的实体。
我使用 Hibernate、Lombok 和 IntelliJ 作为调试器。
当我拉动一个实体树的根时,我得到了一棵对象树。我们姑且称之为“原创”吧。由于与业务需求相关的某种原因,我需要复制它(我们称之为“副本”)。我使用复制构造函数来完成它。 我首先使用直接字段访问编写了复制构造函数的一个版本。
this.someField= original.someField
没成功。当我检查调试器时,我看到original.someField(以及其他字段)始终为空。
尽管如此,它仍然可以使用 setter/getter 来工作。
this.setSomeField(original.getSomeField())
在调试器中,我可以看到原始.handler.target 中的字段已“设置”。 (我不知道 handler.target 是什么)。
有人可以向我解释为什么直接字段访问不起作用吗?
(我问的是技术原因,而不是哲学原因,例如“你应该始终使用 setter/getter ”等)。
我也很高兴知道什么是“handler.target”。
提前致谢。
最佳答案
您遇到的根本不是Java 101问题。 Hibernate 有一个称为延迟加载的功能,它允许框架将(可能很重的)对象的加载推迟到稍后的时间点,仅在需要时。例如,当您加载 account
时,这会很方便。对象只是为了检查 active
标志,但绝对不需要使用此帐户获取所有登录历史记录。
现在是“仅在需要时”部分: setter/getter 。
当您在对象图中的父对象上调用 getter 时,Hibernate 知道您确实需要该可延迟加载的对象。在您这样做之前,延迟引用的对象将保持为空。直接变量访问绕过了执行此“技巧”的代理逻辑,这就是获得意外空值的方法。当通过其 getter 访问该字段时,代理代码就会启动,发生加载,然后您就可以取回对象。
handler/target/etc
只是由于代理而需要的额外引用。 (您的 account
将不再有直接的 accounthistory
变量,而是一个 accounthistory_proxy
,而后者又将有一个 accounthistory_real
)
关于java - 在复制构造函数中使用直接字段访问而不是 getter 会导致空指针异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54194071/