静态块是否在没有main方法的情况下执行?

时间:2013-07-26 19:15:27

标签: java

论坛上有一个问题,

  

静态块甚至在应用程序中没有主方法执行    真的    2.错误

我已将问题回答为2. False,并在我的机器上尝试了以下代码。它没有执行任何操作也没有显示任何错误。

public class StaticBlockDemo {
    static {
        System.out.println("Hello World");
    }
}

那么正确答案是什么?顺便说一下,我正在使用Java 7。

6 个答案:

答案 0 :(得分:36)

如果在System.exit(0) - 块的末尾放置static,它将在Java 6及更低版本中运行时没有错误(没有有效的main!)。这是因为在搜索有效static方法之前执行了<{1}}块,所以如果在静态块结束时退出程序,则会收到no错误。

但是,在Java 7中更改了此行为;现在你必须包含一个明确的main,即使它可能永远不会到达。

在Java 7中,问题的答案是 false ,但在Java 6及以下答案确实是 true


main

Java 6:

Hello World

Java 7:

Error: Main method not found in class Test, please define the main method as:
   public static void main(String[] args)

答案 1 :(得分:5)

静态块在初始化类时执行。通常,main类将导致引导类的初始化,但是还有其他方法来引导程序,例如通过VM的native embedding API

调用类的static main方法会导致其初始化,但许多其他事情也是如此:

  1. 创建该类的实例
  2. 调用任何其他静态方法,
  3. 读取静态字段(非最终字段或具有基本类型或字符串以外的类型)。
  4. 有关详细信息,请参阅JLS chapter 12.4

    以下显示了此操作

    public class Foo {
      static { System.out.println("Foo initialized"); }
    
      public static void main(String... argv) {
        Initialized.callingThisCausesClassInitialization();
      }
    
      static class Initialized {
        static { System.out.println("Initialized initialized"); }
        static void callingThisCausesClassInitialization() {}
      }
    
      static class NotInitialized {
        static { System.out.println("NotInitialized initialized"); }
        static void callingThisCausesClassInitialization() {}
      }
    }
    

    运行foo将打印

    Foo initialized
    Initialized initialized
    

    不会打印

    NotInitialized initialized
    

    因为在执行导致其初始化的程序期间没有执行任何操作。

    看起来你的类有这种行为,因为它从未被使用过,例如上面的NotInitialized

答案 2 :(得分:1)

投票最多的答案主要是&#39;正确,但不完全。 请考虑下面的代码,其中类具有main方法和静态方法。静态方法将在主方法和构造函数之前执行(成功)并生成序列:A B C D - 这可能不像您想象的那样。

public class Sequence {
    Sequence() {
        System.out.print("c ");
    }
    {
        System.out.print("B ");
    }
    public static void main(String[] args) {
        new Sequence().go();
    }
    void go() {
        System.out.print("D ");
    }
    static{
        System.out.print("A ");
    }
}

答案 3 :(得分:1)

在java 8中,如果没有显式编写main方法,则无法运行程序。从这个角度来看答案是假的。没有main方法就不执行静态块。下面是一段显示初始化顺序的代码。(静态块==&gt;主要==&gt;初始化块==&gt;构造函数)

public class StaticBlock {

static{
    System.out.println("in static block");
}


{
    System.out.println("in initialization block");
}

public StaticBlock(){
    System.out.println("in const");
}

public static void main(String[] args) {
        System.out.println("in main method");
        StaticBlock block=new StaticBlock();
}
静态块中的


在主要方法中 在初始化块中 在const

答案 4 :(得分:1)

abstract class test extends javafx.application.Application {
    static {
        System.out.println(“hello”);
        System.exit(0);
    }
}

使用:javac -source 1.6 test.java

进行编译

使用:java test

运行

这甚至适用于JDK 1.8。

答案 5 :(得分:-1)

解释非常详细,但我为这个具体问题抽象了 首先,类加载器子系统在运行时第一次引用它而不是编译时加载一个类。 所以ClassLoader本身是java.lang包中的一个类和

它的实例被称为加载类的classLoader实例 现在详细介绍了它,它遵循一个层次结构,BootStrap ClassLoader位于顶部

请注意,BootStrap类加载器本身是ClassLoader的一个实例。

这些实例更多地执行验证,准备,解析符号引用以保持简单,它执行java程序的动态链接。

现在,当您的编译器编译.java文件时,它会插入一个类型为Class的公共静态final字段 你可以在java.lang.Class中访问它obj = name_of_your_class.class

它包含一个方法getClassLoader,它告诉classLoader实例加载了这个类。

只有通过使用这些信息,ClassLoaders才能知道要加载的类的名称,即其完全限定名称(package.class)

现在在搜索其本机文件系统中的文件并加载它之前 它检查它的父实例它已经加载了该文件nad这个检查传播到顶部BootclassLoader 只有当它们都没有加载它时,只有该实例加载该类文件。 在这种情况下,这些事情如何发生的细节是无关紧要的。

一旦加载了类,静态块就会在类加载器子系统的初始化阶段执行。

因为我已经告诉它的编译器扮演插入该字段的角色。 并注意,未找到main方法是运行时错误,因此编译器不对此负责,而是JVM。

从java 7开始搜索main方法,如果我们没有在运行时得到这个错误 但是在java 6和更早版本中,当类加载时,静态块被激活,然后搜索以查找main方法,但是如果我们提供System.exit(0);在块中它甚至在搜索之前终止程序因此我们没有任何错误

虽然在java 7中探测main方法是在执行静态块之前完成的,静态块本身的执行依赖于main方法的成功发现。尽管程序的执行顺序是程序与java中相同6及早期版本。

进一步详细说明放在堆栈本身的第一个元素应该是主线程。 我们知道执行控制是如何流动的,甚至重要的是注意静态块,即使它们在块中包含本地变量,它们也永远不会作为激活记录放在堆栈上,而是放在方法区域上。 因此,从Java 7开始,JVM检查堆栈上是否存在主线程记录,然后将控制权交给静态块,然后按顺序执行所有静态块。而它在java 6和早期版本中反过来了

同样重要的是要注意我们不能在任何静态或非静态范围内嵌套静态块,因为该块的唯一封闭范围是类的

我甚至知道理解它有点棘手,但阅读这个答案肯定会提供对静态块的良好,准确和深刻的理解。