2

Java 不允许您使用可能尚未在方法范围内初始化的变量。类范围内的未初始化变量仍可能由类方法返回,并且值默认为 null。

为什么对两个不同的作用域进行不同的处理?

public class TestClass {

    Integer i;
    Double d;

    public TestClass() {
        d = 1d;
    }

    public Double getD() {
        return d;
    }

    public Integer getI() {
        return i;
    }

//  public Integer getSomeInt() {
//      Integer i;
//      return i;
//  }

    public static void main(String[] args) {
        TestClass myClass = new TestClass();
        System.out.println(myClass.getI().getClass());
    }
}

这会导致 NullPointerException,但i在 getSomeInt() 中返回是编译器错误,因为“变量可能尚未初始化”。

4

4 回答 4

3

这背后的原因是 Java 的静态代码分析的局限性。编译器能够毫无疑问地证明在初始化之前不会读取堆栈分配的本地变量。这对于堆分配的内存是不可能的,因此 Java 要求在公开指向它的指针之前将所有堆分配的存储清零。

这条规则的结果是所有堆分配的东西都有一个默认值零(假,空,无论二进制零等于该类型)。

于 2012-07-23T12:25:35.353 回答
2

因为成员变量具有默认值(如果未初始化),所以如果您在 nullInull调用方法,它将导致NullPointerException

对于局部变量,在使用之前必须先初始化,否则会变成编译时错误

局部变量略有不同;编译器永远不会为未初始化的局部变量分配默认值。如果您无法在声明它的地方初始化局部变量,请确保在尝试使用它之前为其分配一个值。访问未初始化的局部变量将导致编译时错误。[……]

于 2012-07-23T12:13:36.007 回答
1

这真的很简单。成员变量会自动初始化为其默认值,而局部变量则不会。

当你这样做

public Integer getSomeInt() {
    Integer i;
    return i;
}

隐藏 this.i并在return i你引用一个(未初始化的)局部变量。


那么为什么成员变量会自动初始化而局部变量不会呢?

最终,这是一个只有语言设计者才能回答的问题,但如果我不得不猜测,我会说这是由于必须将所有分配的内存归零的性能问题。然而,当涉及到对象时,强制程序员显式初始化所有字段会很痛苦。


来自 JLS(4.12.3 种变量):

类变量在其类或接口准备好时创建(第 12.3.2 节)并初始化为默认值(第 4.12.5 节)。

[...]

局部变量声明语句可能包含初始化变量的表达式。然而,具有初始化表达式的局部变量在声明它的局部变量声明语句被执行之前不会被初始化。(明确赋值规则(第 16 章,明确赋值)防止局部变量的值在被初始化或以其他方式赋值之前被使用。)

于 2012-07-23T12:14:24.033 回答
0

All fields are implicitly initialized in the constructor after the call to super but before anything else. Object references are set to null, primitive values are set to 0, false etc. This implicit initialization isn't done in methods.

于 2012-07-23T12:15:59.393 回答