【问题标题】:Please explain the execution sequence of my program [duplicate]请解释我的程序的执行顺序[重复]
【发布时间】:2019-12-26 09:30:20
【问题描述】:

我正在尝试了解我的代码的调用顺序。有人,请解释一下调用顺序。

public class MainWithStaticCalls
{
    static
    {
        String[] str = {"1", "2"};
        System.out.println("Static");
        main(str);
    }
    {
        System.out.println("Init block");
    }
    void MainWithStaticCalls()
    {
        System.out.println("constructor");
    }
    public static void main(String[] a)
    {
        MainWithStaticCalls obj = new MainWithStaticCalls();
        NewClass nc = new NewClass();
        nc.callMe();
        System.out.println("Main");
    }

}

class NewClass
{
    public void callMe()
    {
        System.out.println("I'm called");
    }
}

根据我的理解,静态块将在 JVM 开始执行时立即执行,甚至在主类之前。然后实例 init 块被执行。那么构造函数应该被执行。但是如果我们从静态字段调用 main 方法,回调是如何工作的。哪个 main 将首先执行,JVM 正常执行的那个或静态字段显式调用的那个。

My output:
Static
Init block
I'm called
Main
Init block
I'm called
Main

P.S:我已经修改了我的问题。早些时候我将普通方法与构造函数混淆了,所以一些答案可能看起来无关紧要,但这确实有助于我理解问题。

【问题讨论】:

  • 见:java "void" and "non void" constructor。由于虚假的void,您实际上还没有在这里定义构造函数。删除它,它应该可以按预期工作。
  • void MainWithStaticCalls() 是一个方法,而不是一个构造函数。
  • 是的,我明白我做错了什么,谢谢。你能解释一下回调顺序吗?哪个主要方法将首先执行。 JVM调用的或者静态字段显式调用的。

标签: java java-8 constructor


【解决方案1】:

我将尝试用一个例子来解释调用序列,但首先让我们考虑一下,如果你添加了void 访问限定符,这将是一个方法而不是一个构造函数。

其次要记住,一个类可以有两种类型的初始化块:

  • 静态初始化块
  • 实例初始化块

静态初始化块将首先在构造函数之前被调用,因为它处于类级别,甚至在创建任何类实例(即该类类型的对象)之前就会执行。第二个,即实例初始化块在类的新实例创建后立即执行。在这两个块之后,它将被称为构造函数。您可以通过以下示例看到它:

public class MainWithStaticCalls {

    {
        System.out.println("Init block called");
    }

    static {
        String[] str = {"1", "2"};
        System.out.println("Static called");
    }

    public MainWithStaticCalls() {
        System.out.println("this is constructor");
    }

    void MainWithStaticCalls() {
        System.out.println("this is NOT constructor");
    }

    public static void nope() {
        System.out.println("Nope");
    }

    public static void main(String[] a) {
        MainWithStaticCalls.nope();
        System.out.println("************");
        MainWithStaticCalls obj = new MainWithStaticCalls();
        NewClass nc = new NewClass();
        nc.callMe();
        System.out.println("Main");
    }

}

输出是:

Static called
************
Init block called
this is constructor
NewClass: I'm called
Main

如果我注释掉“nope”静态调用:

public class MainWithStaticCalls {

   ... // Same thing as above

    public static void main(String[] a) {
        // MainWithStaticCalls.nope();
        System.out.println("************");
        MainWithStaticCalls obj = new MainWithStaticCalls();
        NewClass nc = new NewClass();
        nc.callMe();
        System.out.println("Main");
    }

}

结果是:

Static called
************
Init block called
this is constructor
NewClass: I'm called
Main

所以如果不注释掉“nope”调用,结果是一样的。这是为了表明静态方法只被调用一次,当类第一次面对 JVM 时。如果我们实例化另一个对象:

public class MainWithStaticCalls {

   ... // Same thing as above

    public static void main(String[] a) {
        // MainWithStaticCalls.nope();
        System.out.println("************");
        MainWithStaticCalls obj1 = new MainWithStaticCalls();
        MainWithStaticCalls obj2 = new MainWithStaticCalls();
        NewClass nc = new NewClass();
        nc.callMe();
        System.out.println("Main");
    }

}

输出是:

Static called
************
Init block called
this is constructor
Init block called
this is constructor
NewClass: I'm called
Main

您会看到,每次创建该类类型的新对象(以及构造函数)时都会调用实例初始化块,而静态初始化块只调用一次。

【讨论】:

  • 嗨安德里亚,这真是一个很好的解释。谢谢你。您能否告诉我如果我们从静态块“main(str);”中调用 main 会发生什么?像这样。
  • 在调用静态初始化程序后(仅一次),您将获得两次对 Init 块的调用:第一次用于创建 obj,因为在静态初始化程序中调用 main(str) 和第二个是为 main 方法本身创建新的 obj 时。
【解决方案2】:

类中没有定义构造函数,所以调用了默认构造函数。

void MainWithStaticCalls()

不是构造函数。这是方法,因为构造函数没有返回类型。

【讨论】:

    【解决方案3】:

    void MainWithStaticCalls() 是方法而不是构造函数。

    改成,

    public MainWithStaticCalls()
    {
       System.out.println("constructor");
    }
    

    为构造函数定义了规则。

    1. 构造函数名必须与其类名相同
    2. 构造函数不能有明确的返回类型
    3. Java 构造函数不能是抽象的、静态的、最终的和同步的

    【讨论】:

    • 是的,我明白我做错了什么,谢谢。你能解释一下回调顺序吗?哪个主要方法将首先执行。 JVM调用的或者静态字段显式调用的。
    【解决方案4】:

    在 Java 中,构造函数不是方法。它只有类的名称和特定的可见性。如果它声明返回一些东西,那么它就不是构造函数,即使它声明返回一个 void 也不是。

    【讨论】:

      【解决方案5】:

      正如其他人已经提到的,您将构造函数与方法混淆了。删除 'void' 使其再次成为构造函数。仅供参考 - 这是 oracle 文档中描述的构造函数:https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-05
        • 1970-01-01
        • 2014-04-16
        • 1970-01-01
        • 1970-01-01
        • 2014-05-29
        • 2012-10-09
        • 1970-01-01
        相关资源
        最近更新 更多