【问题标题】:How java initialize static variables and static method?(with simple code)java如何初始化静态变量和静态方法?(附简单代码)
【发布时间】:2015-04-23 11:32:21
【问题描述】:

我想知道java是如何初始化这些静态变量的。 看不懂的代码如下所示:

public class Main {

static int first=test();
static int second=2;
static int third=test();

public static void main(String[] args) {

    System.out.println(first);
    System.out.println(second);
    System.out.println(third);

}


public static int test() {
    return second;
}

}

下面简单代码的输出是0 2 2

如果编译器会自动忽略不可执行的方法或者静态变量在定义之前为0?

抱歉,谷歌搜索找不到准确的描述。

【问题讨论】:

  • 静态加载类之前加载。这就是为什么它是第一个 0,因为该方法还没有准备好使用。
  • statics 在类之前加载,所以当 test() 首次执行时返回 0。谢谢
  • 一个附加问题。如果我在声明first之前添加static{ System.out.print(first); },就会出现错误。为什么?如果在加载类之前初始化了statics,那么上面的代码应该是有效的。
  • @hsc 在变量初始化之前你仍然不能直接使用它,但是你可以像 firstideone.com/hGqlX5 那样间接使用它
  • @PeterLawrey 非常感谢,终于搞定了

标签: java memory methods static


【解决方案1】:

Java 执行代码时是从上到下。因此,当它初始化变量时,它会从上到下进行。但是,当您读取一个统一的值时,它将是0nullfalse,因为内存首先用零填充。注意:类的静态字段有自己的特殊对象,您可以在堆转储中看到。

所以当你尝试设置时

first = 0; // second hasn't been set yet
second = 2;
third = 2; // second has been set to 2.

添加该方法只会阻止编译器在变量初始化之前检测到您正在尝试使用它。

【讨论】:

  • static int first=test(); 行将调用test() 但为什么它返回second 默认值而不是给出编译器错误说第二个不是declared
  • @singhakash 编译器不会跟踪方法调用的代码来确定您是否使用尚未初始化的变量。在一般情况下,这是一个无法解决的停止问题。知道这一点的唯一方法是实际运行时代码。编译器执行此检查的程度有一个刻意的限制。
  • 不,我是说,正如你所说,java是从上到下的,所以第一行是static int first=test();,它调用test(),但没有声明second变量,那么为什么test()可以返回一个变量没有声明。我说的是声明而不是初始化
  • @singhakashfields 不是动态声明的。每个字段都已经存在于字节码中,并且包含所有字段(静态或非静态)的对象有足够的空间来保存该类将拥有的所有字段。没有一点可以看到未完全分配字段的类或实例。设置它们时唯一可以看到的内容。
  • @singhakash 即使对于局部变量,只要方法调用开始,就会在堆栈上保留空间,它不会逐行在堆栈上分配内存。
【解决方案2】:

这可能会对你有所帮助。

// executing order top to bottom
static int first=test();//test() will return value of second still second is 0
static int second=2;//now second will be 2
static int third=test();//test() will return current value of second, which is 2

public static void main(String[] args) {

    System.out.println(first);// so this will be 0
    System.out.println(second); // this will be 2
    System.out.println(third); // this will be 2

}

public static int test() {
    return second;
}

【讨论】:

    【解决方案3】:

    您可以通过在其中放入一些打印语句来测试编译器是否忽略了不可执行的方法

    public static int test() {
        System.out.println("Test exceuted")
        return second;
    }
    

    现在你的输出可能是:

    Test exceuted
    Test exceuted
    0
    2
    2
    

    这表明该方法已执行,但由于 second 尚未初始化,它第一次返回 0。

    【讨论】:

      【解决方案4】:

      让我们尝试从 JVM 的角度来理解事物:

      加载 - JVM 找到具有特定名称的类型(类/接口)的二进制表示,并从该二进制表示创建类/接口。 静态成员(变量/初始化块)在类加载期间加载 - 按照它们在代码中出现的顺序。

      在这里,作为加载的一部分 - 静态成员按出现的顺序执行。方法test() 被调用了两次;但第一次,变量 second 刚刚被声明,未定义(初始化) - 因此默认为 0。之后,它得到值 2 并打印 - 0 2 2。

      尝试在代码中放置一个静态块并放置一些调试点 - 你自己会看到的。

      【讨论】:

        猜你喜欢
        • 2010-12-11
        • 1970-01-01
        • 2016-03-05
        • 2012-03-30
        • 1970-01-01
        • 2011-08-22
        • 2010-12-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多