“Java语言自动初始化对象的字段,与程序员负责初始化的方法的局部变量形成对比。鉴于您对程序内和程序间数据流分析的了解,请解释语言设计者可能具有的原因做出了这些设计选择。“
对我来说很明显,它可以防止错误。但是,究竟是什么bug呢? 是否要缩小某些给定方法的可能控制流程?
有人可以详细介绍一下吗?我非常感谢你的帮助。
答案 0 :(得分:3)
执行程序内数据流非常容易,因此检查字段是否已初始化非常容易,如果没有,则会发出警告(可以编写一个简单的可判定算法,例如确保所有分支都是if
初始化变量,如果一个分支没有,则失败,即使分支无法访问)。
执行程序间数据流非常困难,因此很难检查某个对象的某个字段是否曾在代码中初始化 (您在任何合理的近似值下快速进入不可判断的领域)。
因此Java执行前者并在检测到未初始化的局部变量时发出编译时错误,但不执行后者并将对象的字段初始化为其默认值。
答案 1 :(得分:1)
它们的初始化并非总是如此。通过结合sun.misc.Unsafe类或ObjectInputStream使用反射来访问这些类私有本机方法或直接通过JNI,可以在不调用任何构造函数的情况下实例化对象。这些用于对象序列化/反序列化的目的,并期望字段由反序列化器填充。至于为什么设计者会选择消除对这些方法的直接访问(即没有反射),理所当然,仍留在内存中的指针可用于堆栈粉碎或返回lib-c攻击。为大多数程序清除为这些“自动”分配的内存可降低安全风险并减少出错的机会。另请注意,尝试读取尚未初始化的局部变量会导致编译错误,原因大致相同