有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么我们可以在类加载之前使用新操作符

考虑到下面的代码,它运行时不会抛出任何异常

public class Test1 {
    public static int k = 0;
    public static Test1 t1 = new Test1("t1");
    public static Test1 t2 = new Test1("t2");
    public static int i = print("i");
    public static int n = 99;
    public int j = print("j");
    {
        print("constructor block");
    }

    static {
        print("static block");
    }

    public Test1(String str) {
        System.out.println((++k) + ":" + str + "    i=" + i + "    n=" + n);
        ++i;
        ++n;
    }

    public static int print(String str) {
        System.out.println((++k) + ":" + str + "    i=" + i + "    n=" + n);
        ++n;
        return ++i;
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Test1 t = new Test1("init");
    }

}

输出:

1:j    i=0    n=0
2:constructor block    i=1    n=1
3:t1    i=2    n=2
4:j    i=3    n=3
5:constructor block    i=4    n=4
6:t2    i=5    n=5
7:i    i=6    n=6
8:static block    i=7    n=99
9:j    i=8    n=100
10:constructor block    i=9    n=101
11:init    i=10    n=102

我用调试器一步一步地完成它。 可以看到clinit方法调用init方法。由于clinit方法仍然是类加载的一部分,这是否意味着我们可以在Test1类准备好之前实例化Test1对象


共 (1) 个答案

  1. # 1 楼答案

    我必须在规范中查找确切的定义(你也可以这样做),但让我们这样说:

    假设你有以下几点:

    class A {
      static B b = new B();
    }
    
    class B {
       static A a = new A(); 
    }
    

    如果在创建新实例之前必须对类进行完全初始化,即所有静态初始值设定项都必须运行,那么就会出现死锁。不允许在静态块中创建新实例将严重限制该语言,因此必须有某种方法来解决这个问题

    正如我所说,我必须查找这个,但默认顺序如下:

    • 类被加载,静态变量被初始化为它们的默认值
    • as构造函数被称为自上而下(即从超级类到子类)
      • 首先,按照定义顺序调用静态初始值设定项块(即初始化静态变量以及静态块)
      • 然后执行当前类的实例初始值设定项块并
      • 最后执行构造函数

    当然,正如你已经发现的那样,有一些方法可以扰乱秩序,但通常不建议这样做,因为你最终可能会出现未定义/混乱的行为。其中一种情况是在超类构造函数中调用一个方法,该方法在子类中被重写,并访问子类的字段(尚未初始化)