【问题标题】:Creating object using static keyword in Java在 Java 中使用 static 关键字创建对象
【发布时间】:2014-09-15 15:15:53
【问题描述】:
class abc {
    int a = 0;
    static int b;
    static abc h = new abc(); //line 4

    public abc() {
        System.out.println("cons");
    }

    {
        System.out.println("ini");
    }

    static {
        System.out.println("stat");
    }
}

public class ques {
    public static void main(String[] args) {
        System.out.println(new abc().a);
    }
}

当我编写这段代码时,我得到的输出是这样的:

ini
cons
stat
ini
cons
0

在这里,当我在main(), class abc 中创建一个新对象时,已加载并static 变量和块按写入顺序执行。当控制到达第 4 行时,static abc h = new abc(); 调用实例初始化块。为什么?为什么在第 4 行创建新对象时不调用静态块,直到那时静态块也没有被调用一次,所以根据惯例应该调用静态块。为什么会出现这种意外输出?

【问题讨论】:

  • 静态代码只运行一次,所以当第二个对象被创建时(在第一个对象内)它不会被执行。我很惊讶ini 在此时执行。
  • @DavidPostill- 标记的帖子清除了静态初始化通常如何发生的概念。但我的主要问题是为什么在第 4 行没有调用静态块,而是调用了实例初始化块。
  • 当我调试你的代码时,我可以看到在第 4 行调用了静态块,这是由于静态初始化而调用它的唯一地方。如果删除静态成员,首先调用静态块。
  • @Duncan 我只是想让实例初始化程序更容易看到,但如果你这么说我不会争论。回想起来,您实际上是对的,我应该添加 1 个换行符而不是 2 个。

标签: java static initialization


【解决方案1】:

JLSsays:

静态初始化器和类变量初始化器被执行 以文本顺序,并且不能引用在 其声明在使用后以文本形式出现的类,即使 这些类变量在范围内(第 8.3.2.3 节)。这个限制是 旨在在编译时检测最循环或其他 格式错误的初始化。

这正是你的情况。

这是您的原始示例:http://ideone.com/pIevbX - abc 的静态初始化程序 after 分配了 abc 的静态实例 - 因此无法执行静态初始化程序 - 它在静态之后的文本变量初始化

让我们移动第 4 行 静态初始化块 - http://ideone.com/Em7nC1

class abc{
int a = 0;
static int b;
public abc() {
    System.out.println("cons");
}
{
    System.out.println("ini");
}
static {
    System.out.println("stat");
}
static abc h = new abc();//former line 4

}

现在您可以看到以下输出:

stat
ini
cons
ini
cons
0

现在初始化顺序更符合您的预期 - 首先调用静态初始化程序,然后以常用方式初始化 abc 的静态实例。

【讨论】:

    【解决方案2】:

    静态字段初始化和静态块按照它们声明的顺序执行。在您的情况下,分离声明和初始化后的代码等价于:

    class abc{
        int a;
        static int b;
        static abc h;//line 4
    
        static {
            h = new abc();//line 4 (split)
            System.out.println("stat");
        }
    
        public abc() {
            a = 0;
            System.out.println("ini");
            System.out.println("cons");
        }
    }
    
    public class ques{
        public static void main(String[] args) {
            System.out.println(new abc().a);
        }
    }
    

    因此,当您从代码到达第 4 行时,静态初始化实际上正在执行但尚未完成。因此,您的构造函数在 stat 可以打印之前被调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-30
      • 1970-01-01
      • 2016-12-03
      • 2010-12-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多