Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用继承时,静态块和初始化块的执行顺序是什么?_Java_Inheritance_Constructor_Static Block - Fatal编程技术网

Java 使用继承时,静态块和初始化块的执行顺序是什么?

Java 使用继承时,静态块和初始化块的执行顺序是什么?,java,inheritance,constructor,static-block,Java,Inheritance,Constructor,Static Block,我有两个班:父母班和孩子班 public class Parent { public Parent() { System.out.println("Parent Constructor"); } static { System.out.println("Parent static block"); } { System.out.println("Parent initialis

我有两个班:父母班和孩子班

public class Parent {    
    public Parent() {
        System.out.println("Parent Constructor");
    }    
    static {
        System.out.println("Parent static block");    
    }    
    {
        System.out.println("Parent initialisation  block");
    }
}

public class Child extends Parent {    
    {
        System.out.println("Child initialisation block");
    }
    static {
        System.out.println("Child static block");
    }

    public Child() {
        System.out.println("Child Constructor");
    }    
    public static void main(String[] args) {
        new Child();    
    }
}
上述代码的输出将是

Parent static block
Child static block
Parent initialization  block
Parent Constructor
Child initialization block
Child Constructor

为什么Java会按这种顺序执行代码?决定执行顺序的规则是什么?

有几个规则在起作用

  • 静态块总是在创建对象之前运行,因此您可以看到来自父静态块和子静态块的打印消息
  • 现在,当您调用子类(child)的构造函数时,该构造函数隐式地调用
    super()在执行它自己的构造函数之前。初始化块甚至在构造函数调用之前就开始起作用,所以它首先被调用。所以现在您的父类已经创建,程序可以继续创建子类,子类将经历相同的过程
解释:

  • 首先执行父级的静态块,因为它是先加载的,并且在加载类时调用静态块

  • java中的静态块在main方法之前执行。若我们在java类中声明一个静态块,它将在类加载时执行。这是用静态变量初始化的。它主要用于JDBC。java中的静态块每次加载类时都会执行。这也称为静态初始化块。java中的静态块在类加载到内存时初始化,这意味着JVM读取字节码时。初始化可以是任何东西;它可以是变量初始化,也可以是该类的所有对象共享的任何其他内容。静态块是用大括号{}括起来的普通代码块,前面有Static关键字

    所以先执行静态块

    实例初始化块:每次创建类的实例时运行

    所以,在创建类的实例时执行下一个初始化块


    然后,构造函数执行了第一个只运行子类(注释extend子句)来查看简单流

    第二,去阅读那边被接受的答案

    编辑:

  • 执行以SIC方式进行-静态,(非静态)初始值设定项和构造函数
  • (非静态)初始值设定项被复制到每个构造函数中-在顶部!(因此第3/4/5/6行)
  • 在初始化一个类之前,必须初始化它的直接超类-(因此首先出现父静态块)

  • 静态块在类加载到JVM时执行。而init block被复制到构造函数中,该构造函数的对象将被创建并在创建对象之前运行。

    使用一个分步调试程序检查对象构造过程将非常有帮助,在这个视图中,您可以看到对象是如何通过各个阶段运行的。我发现这对于从更高的角度澄清观点非常有用。Eclipse可以帮助您实现这一点,它的调试器一步到位功能。

    我以可视化方式学习,因此这里是顺序的可视化表示,如下所示:

    公共类示例{
    静止的{
    步骤(1);
    }
    公共静态int步骤2=步骤(2);
    公共int步骤8=步骤(8);
    公共示例(int未使用){
    超级();
    步骤(10);
    }
    {
    步骤(9);
    }
    //仅出于演示目的:
    公共静态整数步(整数步){
    System.out.println(“步骤”+步骤);
    返回步骤;
    }
    }
    
    公共类Example子类扩展示例{
    {
    步骤(11);
    }
    公共静态int步骤_3=步骤(3);
    公共int第12步=第(12)步;
    静止的{
    步骤(4);
    }
    公共示例子类(int未使用){
    super(步骤(7));
    步骤(13);
    }
    公共静态void main(字符串[]args){
    步骤(5);
    新示例子类(步骤(6));
    步骤(14);
    }
    }
    
    这张照片是:

    步骤1
    步骤2
    步骤3
    步骤4
    步骤5
    步骤6
    步骤7
    步骤8
    步骤9
    步骤10
    步骤11
    步骤12
    步骤13
    步骤14
    
    请记住,
    静态
    部件的顺序很重要;回顾一下
    Example
    static
    stuff和
    ExampleSubclass
    的顺序之间的区别

    还请注意,实例初始化块总是在构造函数中的
    super()
    调用之后立即执行(即使该调用是隐含的/省略的),无论顺序如何。但是,初始化块和字段初始值设定项之间的顺序并不重要。

    控制流是-

    静态块->初始化块->最后是构造函数。

    静态块->当控件到达类时,该静态块只执行一次(JVM加载该类)

    初始化块->每当为类创建新对象时,就会执行此初始化块(它将从构造函数的第二条语句开始执行,然后从后面的构造函数语句开始执行-记住构造函数的第一条语句将是Super()/This())


    构造函数->每当创建一个新对象时,都会得到它。

    只是想分享我的发现。 我在另一个线程的一个答案中读到,静态块首先在静态字段之前执行,这是不正确的。这取决于哪个先到,静态字段还是静态块。看看下面的代码。它将努力把事情放在正确的角度

  • JVM查找具有公共静态void main(字符串args[])的类,以便加载该类
  • 然后初始化此类的静态字段(如果它们位于静态块之前)。这些字段可以调用此类或其他类的静态方法。若他们调用此类的静态方法,那个么该方法将得到服务。若他们调用另一个类的静态方法,那个么该类的静态字段或块(取决于哪个先到)首先被初始化,然后这个方法调用被服务
  • 然后,它移动到静态块。class TestLab { static int method(String a) { System.out.println("in static method of TestLab" + " Coming from " + a); System.out.println("b is " + b); return 6; } static int a = method("Line 11"); static int b = 7; TestLab() { System.out.println("Inside test lab constructor"); } static { System.out.println("In static block of TestLab"); } } public class Test1 { public static void main(String[] args) { System.out.println("inside main method of Test 1"); int a = TestLab.method("Line 26"); } // static Test ref=new Test(); Test1() { System.out.println("Default Constructor of Test1"); } { System.out.println("In instance block of Test1"); } static int d = TestLab.method("Line 37"); static int e = methodOfTest1(); static { System.out.println("In Static Block of Test1"); } static int methodOfTest1() { System.out.println("inside static method:mehtodOfTest1()"); return 3; } }
    in static method of TestLab Coming from Line 11
    b is 0
    In static block of TestLab
    in static method of TestLab Coming from Line 37
    b is 7
    inside static method:mehtodOfTest1()
    In Static Block of Test1
    inside main method of Test 1
    in static method of TestLab Coming from Line 26
    b is 7