【问题标题】:How does the compiler handle Main when instantiating own class实例化自己的类时编译器如何处理Main
【发布时间】:2015-08-02 14:16:25
【问题描述】:

编辑:澄清:

创建一个包含静态 main 的新类。在 main 方法中实例化同一个类。当 JVM 在实例化时到达主方法代码行时会做什么?

(JVM如何知道在while循环期间“跳过”以下代码中的静态main()方法)

我问是因为我看不出将 static main 放入您打算实例化的类中有任何好处,将 static main 放入专门为此目的而构建的“启动器”类似乎要好得多启动应用程序..

对狗类感到困惑:

public class Dog {
    private int height;

    public static void main (String[] args) { // <---- What does the JVM do when it reaches here during the object instantiation?
        int i = 0;
        Dog [] dogArray = new Dog[20];
        while (i < 20){
             dogArray[i] = new Dog(); // Instantiate knew class
             dogArray[i].height = i*10; //whatever
             i++;
        }
    }
}

当然最好创建两个类,在这种情况下:

public class Dog {
    private int height;

    getHeight{//etc...}
    setHeight{//etc...}
}

public class launchApplication{
public static void main (String[] args) {
    int i = 0;
    Dog [] dogArray = new Dog[20];
    while (i < 20){
         dogArray[i] = new Dog(); // Instantiate knew class
         dogArray[i].setHeight = i*10; //whatever
         i++;
    }
}

}

【问题讨论】:

  • 您认为main 方法是什么?你为什么这么认为?
  • 我认为它是 JVM 寻找启动应用程序的内容 - 以及找到它后接下来要做什么。这就是为什么将 main 方法粘贴在具有其他功能的类中似乎是随机的,将主方法赋予它自己的“启动器”类会更清楚 OO,并将其他类保留为纯对象蓝图。
  • 您似乎认为 JVM 只是执行它在一个类中找到的所有代码。 Java 不是这样工作的。
  • ...它不会“迭代”它。
  • 它加载符号表,然后调用表中方法指向的代码。如果您想了解底层细节,只需阅读 JVM 规范;没有比这更容易的了。

标签: java compiler-construction static jvm main


【解决方案1】:
public class Test {

    /**
     * The constructor
     */
    public Test() {
        System.out.println("The is the constrcutor");
    }

    /**
     * The main method
     * 
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("This is main");

        new Test();
        new Test();
        new Test();
    }

    /**
     * A static method
     */
    public static void count() {
        System.out.println("This is a static method");
    }

    /**
     * A static block
     */
    static {
        System.out.println("This is the static block");
    }
}

输出:

这是静态块

这是主要的

是构造器

是构造器

是构造器

运行上面的代码,你会对此有更好的了解。

main 方法由 jvm 在您运行程序时调用。为什么实例化Test类时要调用它。

当你实例化一个类时,首先会执行静态块。这将是第一次实例化,而不是全部。 (查看输出)。

然后会调用构造函数。

如果您查看输出,则不会调用任何静态方法。静态方法只有在被调用时才会被调用。这就是count() 在这种情况下没有执行的原因。 main方法被JVM调用一次,启动程序,但之后它仍然是该类的常规静态方法,它不会执行它被调用的util。

【讨论】:

  • 不就是调用类的Test方法吗?如果您将类视为对象的蓝图,那么在随机类中包含 main 似乎很混乱。为启动应用程序而创建一个“类”感觉要好得多,然后您可以在其中创建测试类并运行测试方法。
  • Test() 这里是 constructorTest 这里。不管你写不写,当你实例化一个对象时它总会被调用。是的,最好不要管有main 的类,只为调用而编写POJO 类,然后把所有的东西都清理干净。但是要回答您的问题,对象创建不会调用main
  • 谢谢,所以如果该类碰巧包含一个主方法,那么在实例化对象时,JVM 会忽略主方法?还有什么它忽略的吗?
  • @LeonKowalski 这里没有忽略任何东西,为了证明这一点,只需创建一个带有一些静态方法的类并实例化该类,您会看到不会调用静态方法,就像count()我的代码中的方法。
  • 我很困惑,因为在我的示例中,在实例化每个新 Dog 对象的 while 循环期间,JVM 不会再次运行静态 main 方法 - 但是在第一次启动该类时,它会运行。那么 JVM 是如何确定何时使用 main 何时不使用的呢?我在这里没有意义吗?
【解决方案2】:

事实证明,我一直在寻找的答案(以及我试图提出的问题)实际上是 JVM 是如何进行引导和调用 main 的。是本机代码首先启动 JVM,并使用 STATIC 调用 main 方法,以避免必须先以某种方式(外部)创建对象,然后从该对象调用 main 方法。

我对 main 方法为什么被“忽略”的困惑是对 main 方法的调用方式的误解 - 它是由 JVM 在启动期间显式调用,这就是JAVA 约定 - JVM 是以这种方式构建和设计的,它是一种专用方法。

因此,在我的示例中,main 作为一个方法,在 main 所属的类的每个实例化期间都不会被调用(因为在实例化期间不会隐式调用方法),我的印象是 main 在任何时候都会以某种方式自动调用一个类是由于它是“java main 方法”而被实例化的——就好像它有一个要调用的钩子一样。关键在于掌握 STATIC 以及 JVM 如何加载 Main 方法而不首先实例化它的封闭类。这实质上是从 JVM(包括本机)引导程序过程到正在运行的 JAVA 应用程序的更“纯粹”的面向对象能力的过渡。

希望这是有道理的,并希望它可以帮助某人澄清一些事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-30
    • 1970-01-01
    相关资源
    最近更新 更多