【问题标题】:Output based sequencing [duplicate]基于输出的排序[重复]
【发布时间】:2013-06-09 05:10:24
【问题描述】:

我无法理解为什么在 'c' 之前打印 'y'...我在这里遗漏了什么.. 请帮忙

public class Sequence {

    Sequence() {
        System.out.print("c ");
    }

    {
        System.out.print("y ");
    }

    public static void main(String[] args) {
        new Sequence().go();
    }

    void go() {
        System.out.print("g ");
    }

    static {
        System.out.print("x ");
    }
}

【问题讨论】:

  • @PSR 它编译得很好。
  • 这里没有编译错误
  • System.out.print("y");语句是单独的?是什么意思
  • @PSR 这是一个实例初始化程序块,它在 every 构造函数的对象实例化时运行,但它在调用的实际构造函数的主体之前执行(因此y 是在c 之前打印)。
  • @PSR 下次测试代码,然后说它不会编译。

标签: java


【解决方案1】:

下面的说明应该会有所帮助:(按顺序执行)

  • static {}:加载类时执行此块。这称为静态初始化块。
  • {}:每次创建类的新实例时都会执行此块。这称为实例初始化块。
  • Sequence():在上述代码块之后,构造函数在新实例创建时执行。

【讨论】:

    【解决方案2】:

    输出是

    x y c g
    

    在java中,执行顺序如下。

    1. 加载类时调用静态块 - 打印 x
    2. 在创建新实例时调用初始化程序块(就在构造函数执行之前) - 打印y
    3. 构造函数 - 打印 c

    然后你调用了打印g的方法go()

    假设 Sequence 继承自 SuperSequence。

    public class SuperSequence() {
        static {
            System.out.print("staic of super ");
        }
        public SuperSequnce() {
            System.out.print("constructor of super ");
        }
    }
    

    输出将是

    static of super x constructor of super y c g
    

    因为先执行超类的静态块。然后是Sequence类的静态块。

    【讨论】:

    • 不是无名块被称为初始化块,定义要在超类构造函数之后,类构造函数之前执行。
    • 我的错。初始化块。我努力回忆它的名字。谢谢指正:)
    • IMO,如果您可以在答案中表明即使在初始化块之前调用超类构造函数并提供示例,那就太好了(请注意,这在建议的重复 Q/As 中的任何地方都没有解释)。
    • 我明白你的意思。但是,在这个问题中,哪个是超级类?
    • 无处可去,但这将是以前没有人解决的问题(因此在其他提供的答案之间产生了巨大的差异)。同样,这只是我的意见:)。
    【解决方案3】:

    在java中静态块总是先执行,然后是初始化块,写成
    {
    //...your code to initialize any variable
    }

    剩下的两个像构造函数Sequence()void go();这样的块方法将相应地执行。
    根据 java 的关于初始化块的官方文档是:

    Java 编译器将初始化程序块复制到每个构造函数中。因此,这种方法可以用来在多个构造函数之间共享一个代码块。

    看看这个oracle documentation link

    【讨论】:

      【解决方案4】:

      我更改了问题的源代码,在超类中添加了一个超类和一个静态块。下面的代码打印:

      测试静态 x zy c g

      代码:

        class test{
      
          static{
              System.out.print("test static ");
          }
      
          public test(){
              System.out.print("z");
          }
        }
      
        class Sequence extends test { 
      
          Sequence(){
              System.out.print("c ");
          }
      
          { 
            System.out.print("y "); 
          } 
      
          public static void main(String[] args) { 
      
              new Sequence().go(); 
          } 
      
          void go(){
              System.out.print("g "); 
              } 
      
          static {
              System.out.print("x ");
              } 
          } 
      

      所以它就像 Luiggi Mendoza 所说的那样工作:

      1. Super 类的静态块。
      2. 子类的静态块。
      3. 超类构造函数。
      4. 初始化程序块。
      5. 子类构造函数。

      【讨论】: