请用java解释这种行为

请用java解释这种行为,java,inheritance,constructor,initialization,instance,Java,Inheritance,Constructor,Initialization,Instance,输出-----------------> A. C Z B F D Z b 我认为这个-->>>>TestStart x=new abc()的输出行为--------应该是:- 两个类的第一个静态块都将运行 然后,由于新的abc(),子类的init块将被调用。但在这里,父类的init将被调用 然后从new abc()调用super(),从而调用父类构造函数 在父类构造函数之前,将执行父类的init块 然后将执行parnet类的构造函数 然后将执行子类的构造函数 我应该得到以下输出: A. C F

输出-----------------> A. C Z B F D Z b

我认为这个-->>>>TestStart x=new abc()的输出行为--------应该是:-

  • 两个类的第一个静态块都将运行
  • 然后,由于新的abc(),子类的init块将被调用。但在这里,父类的init将被调用
  • 然后从new abc()调用super(),从而调用父类构造函数
  • 在父类构造函数之前,将执行父类的init块
  • 然后将执行parnet类的构造函数
  • 然后将执行子类的构造函数
  • 我应该得到以下输出: A. C F Z B D Z b

    这种行为主要源于父类和子类中是否没有init块。
    请解释我提到的输出。

    初始化后,所有类中的静态块和变量都会运行父类的初始化器。在父构造函数之后,然后是子构造函数中子构造函数的初始值设定项。 这是因为您可以在子初始值设定项中使用一些父字段,因此必须在初始化之前对它们进行初始化

    首先,一些命名:

    class abc extends TestStart{
         static{
             System.out.println("c");
         }
         {
             System.out.println("f");
         }
         public abc(){
             System.out.println("d");
         }
    }
    
    public class TestStart {
         static {
             System.out.println("A");
         }
         {
             System.out.println("z");
         }
         public TestStart(){
             System.out.println("b");
         }
    
         public static void main(String[] args) {
    
             TestStart x = new abc();
             TestStart y = new TestStart();             
         }
    }
    
    首先调用静态初始值设定项是正确的,但唯一的保证是在任何上下文中使用该类之前调用类静态初始值设定项

    对于实例初始值设定项和构造函数,调用顺序如下,从第一次调用到最后一次调用:

     public class TestStart {
       static { // static initializer
         System.out.println("A");
       }
       { // instance initializer
         System.out.println("z");
       }
       public TestStart() { // constructor
         System.out.println("b");
       }
     }
    

    如果使用
    this()
    ,从同一个类调用其他构造函数,初始化器在所有构造函数调用您的类之前被调用一次。

    您得到:
    A
    c
    z
    b
    f
    d
    z
    b
    而您期望的是:
    A
    c
    f
    b
    z
    b

    那么,您是说您希望
    f
    发生在
    z
    b
    之前

    所以,你的基本意思是,你期望:

    • 最派生类(
      f
      )的实例初始值设定项
    在之前被调用

    • 基类(
      z
      )和
    • 基类的构造函数(
      b
    嗯,事情不是这样发生的。基类的所有实例初始化必须在派生类的实例初始化开始之前完成,否则派生类将能够访问基类的未初始化成员


    所有静态初始化的东西(
    A
    c
    )都是为了迷惑我们而在问题中抛出的红鲱鱼。

    但是调用父类构造函数背后的原因是super()在子类构造函数内部。这就是为什么父类构造函数首先运行。在调用构造函数之前,init block应该运行。我不会在super()之后运行sir初始化器。“然后子类的init block将被调用,因为新的abc()”这听起来像是从屋顶开始建造房子。。。初始化父实例是子类的基础,因此需要首先构建。
    Parent initializer, Parent Constructor, Your Initializer, Your Constructor