2012-07-23 36 views
2

Java不允许你使用可能还没有一个方法范围内初始化的变量。类范围内的未初始化变量仍然可以由类方法返回,并且该值默认为null。为什么使用未初始化的变量时,java的治疗类范围和方法范围不同?

为什么不同的处理两个不同的范围呢?

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,但在返回内getSomeInt i()是一个编译器错误,因为“变量可能没有被初始化”。

回答

3

背后的原因是Java静态代码分析的局限性。编译器能够毫无疑问地证明,在初始化之前,您不会读取堆栈分配的本地var。对于堆分配的内存来说这是不可能的,因此Java要求在将指针暴露给它之前将所有堆分配的存储设置为零。

该规则的结果是,所有堆分配的默认值都为零(false,null,无论二进制零对于该类型而言)。

+0

谢谢,这是我正在寻找的答案。为什么堆分配资源不可能检查它们是否已初始化? – user831885 2012-07-23 13:31:02

+0

因为它们可以很容易地发布到外星代码甚至其他线程。这使得理论上不可能在第一次读取之前确保初始化。 – 2012-07-23 13:32:05

2

因为成员变量的默认值(如果未初始化)等等Inull,如果你对空调用方法会导致对NullPointerException

和局部变量,它们必须被初始化之前以其他方式使用它会变成编译时错误

局部变量是略有不同;编译器从不将默认值分配给未初始化的局部变量。如果你不能初始化在声明局部变量,请确保您尝试使用它之前,它分配一个值。访问未初始化的本地变量将导致编译时错误。 [....]

+0

如果它是一种基本的数据类型,并且它是好的,但是如果它是一个对象哦,它在被访问时会抛出NullPointerException,并且它看起来不太好,至少约束可能已经存在于非原始类成员 – Jayy 2012-07-23 12:21:37

+0

使用构造函数初始化默认值 – 2012-07-23 12:29:18

1

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

当你

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

隐藏this.ireturn i你指的是(初始化)当地变量。


那么为什么的成员变量初始化时自动局部变量都没有?

归根结底,这是只有语言的设计者可以回答的问题,但如果要我猜我会说这是由于其零出被分配所有内存的性能问题。当涉及到对象时,强制程序员显式初始化所有字段会是一种痛苦。


从JLS(变量4.12.3种):

当制备它的类或接口(§12.3.2)和 被初始化为缺省,创建一类可变值(§4.12.5)。

[...]

局部变量声明声明可以含有 初始化变量的表达式。与初始化表达式中的局部变量然而 未初始化,直到 声明它执行局部变量的声明语句。(它已 被初始化之前被使用明确赋值(第16章,正定 分配)防止从本地变量的值的规则或以其他方式分配一个值。)

+0

+1,但我认为OP在质疑多一点。他指出了方法和类变量的不同行为。所以解释了为什么方法变量默认没有被初始化,但是类成员会帮助我想。 – 2012-07-23 12:19:12

0

所有字段被设置在隐式初始化构造函数在super之后但在其他之前。对象引用设置为null,原始值设置为0,false等。 此隐式初始化不在方法中完成。

+0

此外,编译器可以通过检查代码流来判断局部变量是否已初始化。对于一个成员变量来说,它比较困难,而且意味着仔细阅读所有不同的方法调用。但是,不能保证任何这些方法都被调用。编译器几乎忽略了这一点,虽然像eclipse这样的工具可以很好地告诉你什么时候一个变量从来没有被读过或写过它声明的类中。 – Matt 2012-07-23 12:27:39