【问题标题】:Calling a Java method with no name调用没有名称的 Java 方法
【发布时间】:2021-12-30 23:00:25
【问题描述】:

我在看下面的代码,发现有些奇怪:

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 ");
    }
}

我预计这会产生编译错误,因为带有“y”的System.out 不属于方法声明,而只是{ }。为什么这是有效的?我看不出应该如何调用这段代码。

当运行它时,它也会产生x y c g,为什么static { } 在序列构造函数之前被调用?

【问题讨论】:

    标签: java initializer


    【解决方案1】:

    这个:

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

    是一个静态初始化块,在类加载时被调用。您可以在您的班级中拥有任意数量的它们,并且它们将按照它们的出现顺序(从上到下)执行。

    这个:

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

    是一个初始化块,代码被复制到类的每个构造函数的开头。因此,如果您的类有许多构造函数,并且它们都需要在开始时做一些共同的事情,那么您只需要编写一次代码并将其放入像这样的 初始化块中。

    因此您的输出非常有意义。

    正如Stanley 在下面评论的那样,请参阅the section in the Oracle tutorial describing initializaiton blocks 了解更多信息。

    【讨论】:

    • 很好的答案。在http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html 了解有关初始化块的更多信息
    • the code is copied into the beginning of each constructor of the class - 这是不正确的。假设构造函数以super("x "); 开头,超级构造函数将在任何初始化块之前执行。
    • 是的,对超级构造函数的隐式和显式调用将首先执行,然后是初始化块,然后是其余的构造函数代码。
    【解决方案2】:

    它不是一个方法,而是一个初始化块

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

    它将在构造函数调用之前执行。 而

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

    静态初始化块,在类加载器加载类时执行。

    所以当你运行你的代码时

    1. 类由类加载器加载,因此执行静态初始化块
      输出:x 被打印出来
    2. 对象被创建,所以初始化块被执行,然后构造函数被调用
      输出:打印 y 后跟 c
    3. 调用主方法,然后调用 go 方法
      输出:g 被打印出来

    最终输出:x y c g
    这可能会帮助http://blog.sanaulla.info/2008/06/30/initialization-blocks-in-java/

    【讨论】:

    • @Cthulhu:谢谢。它一直有效到上周我已经用新链接更新了它。
    【解决方案3】:

    这是一个实例初始化块,后跟一个静态初始化块

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

    在您创建类的实例时被调用。

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

    当类被类加载器加载时被调用。所以当你这样做时

    new Sequence().go();
    

    类被加载,所以它执行static {},然后它执行实例初始化块{},然后调用构造函数的主体,然后是新创建的实例上的方法。因此输出x y c g

    【讨论】:

      【解决方案4】:
      static {
              System.out.print("x ");
          }
      

      是一个静态块,在类加载过程中被调用

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

      是一个初始化块

      一个类中可以有多个初始化块,在这种情况下,它们会按照它们在类中出现的顺序执行。

      请注意,类中存在的任何初始化块都在构造函数之前执行。

      【讨论】:

        【解决方案5】:
        static {
              System.out.print("x ");
        }
        

        是类共享的初始化块(static表示),先执行。

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

        是类的所有对象(构造函数)共享的初始化块,接下来是。

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

        是该类的特定构造函数,第三个执行。每次执行构造函数时都会首先调用实例初始化块。这就是为什么“y”出现在“c”之前的原因。

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

        只是与使用上面的构造函数构造的对象相关联的实例方法,这是最后一个。

        【讨论】:

          【解决方案6】:
          {
              System.out.print("y ");
          }
          

          这些类型的块被称为 initializer block。每次创建class 的实例时都会执行它。 在编译时,此代码被移动到类的每个构造函数中。

          static initializer 块的情况下:-

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

          它在类加载时执行一次。 我们一般在初始化一个static字段时使用static初始化块,需要多个步骤。

          【讨论】:

            【解决方案7】:

            它用作初始化块并在任何静态声明之后运行。它可以用来确保没有其他人可以像 Singleton 设计模式一样创建类的实例(与使用私有构造函数相同)。

            【讨论】:

              【解决方案8】:
              static {
                  System.out.print("x ");
              }
              

              Static blocks 仅在加载类并由 JRE 初始化时执行一次。

              并且non-static 块将在每次创建新实例时调用,并且将在构造函数之前调用。

              在这里,您只创建了 1 个 Sequence 实例,因此在 non-static 块之后调用了如此构造的实例,然后调用了实际目标的方法。

              【讨论】:

                猜你喜欢
                • 2012-10-03
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-03-07
                • 1970-01-01
                • 2012-11-16
                • 1970-01-01
                相关资源
                最近更新 更多