68

谁能解释一下Java是如何执行这段代码的?我的意思是执行每个语句的顺序。

public class Foo
{
    boolean flag = sFlag;
    static Foo foo = new Foo();
    static boolean sFlag = true;

    public static void main(String[] args)
    {
        System.out.println(foo.flag);
    }
}

输出:

false
4

5 回答 5

104
  • 类初始化开始。最初,foo为空且sFlag为假
  • 第一个静态变量初始化程序 ( foo) 运行:
    • Foo创建了一个新的实例
    • 用于执行的实例变量初始值设定项flag- 当前sFlag为 false,因此值为flagfalse
  • 第二个静态变量初始化器 ( sFlag) 执行,将值设置为 true
  • 类初始化完成
  • main运行,打印出来foo.flag,这是错误的

请注意,如果sFlag被声明为final,它将被视为编译时常量,此时对它的所有引用基本上都将被内联到true,因此foo.flag也是如此。

于 2012-05-16T07:30:05.683 回答
12

foo在类的静态初始化期间和 sFlag 初始化之前实例化,布尔值的默认值为 false。

  1. 类已加载
  2. Foo 被初始化为实例

    2.a实例成员标志初始化为sFlag的值(false默认)

  3. sFlag 初始化为true

有关详细信息,请参阅JLS §12.4

于 2012-05-16T07:29:17.320 回答
5

当类被加载,sFlag并且foo字段被初始化但foo首先被初始化!
字段flagsFlag是布尔值,不能为空,所以默认情况下是假的,在初始化sFlag时仍然是假的。在这之后是假的。就是这样fooflag = sFlagflag

于 2012-05-16T07:31:25.387 回答
2

初始化操作的一般顺序是(在加载类之后和第一次使用之前):

  1. 静态(类)代码块按顺序出现在代码中,
  2. 对象代码块按其出现在代码中的顺序(初始化块和赋值)。
  3. 构造函数

当然,我不会将构造函数和函数体称为上面的代码块

我不知道final static字段如何。看起来它们遵循static字段规则,并且在声明之前无法引用它们,尽管之前有评论说它们是在编译步骤初始化的。如果在出现编译错误之前引用它们:

Example.java:8: illegal forward reference
        System.err.println("1st static block j=" + j);

也许final static字段可以初始化并编译到类文件中,但这不是一般规则,在声明之前仍然不能引用它们。

检查初始化顺序的示例代码:

class Example {    

    final static int j = 5;

    {
        System.err.println("1st initializer j=" + j);
    }

    static {
        System.err.println("1st static block j=" + j);
    }

    static {
        System.err.println("2nd static block j=" + j);
    }

    final static java.math.BigInteger i = new java.math.BigInteger("1") {    
        {
            System.err.println("final static anonymous class initializer");
        }
    };

    Example() {
        System.err.println("Constructor");
    }

    static {
        System.err.println("3nd static block j=" + j);
    }

    {
        System.err.println("2nd initializer");
    }

    public static void main(String[] args) {
        System.err.println("The main beginning.");
        Example ex = new Example();
        System.err.println("The main end.");
    } 
}

上面的代码片段打印:

1st static block j=5
2nd static block j=5
final static anonymous class initializer
3nd static block j=5
The main beginning.
1st initializer j=5
2nd initializer
Constructor
The main end.
于 2012-05-23T10:04:12.287 回答
1

起初静态字段应该运行并且首先内联!所以在第一行第 4 行,然后第 5 行将运行,所以首先初始化 foo 并且我们知道布尔变量默认初始化为 false 所以首先,当 foo 被初始化时,flag 的字段是 sflag,它是 false,然后 sfalsg 变为 true不会改变标志(没有关系)然后最后主要运行并打印错误的 falg !!!希望有用!成功的

于 2012-05-23T07:42:33.463 回答