21

我正在尝试在我的机器上运行以下代码,但它没有执行任何操作,也没有显示任何错误。

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

有人可以帮帮我吗?顺便说一句,我使用的是 Java 7。

4

6 回答 6

36

如果您在-blockSystem.exit(0)的末尾加上 a,它将在 Java 6 及更低版本中正常运行(没有有效的!)。这是因为该块是在搜索到有效方法之前执行的,因此如果您在静态块的末尾退出程序,您将不会收到任何错误。staticmainstaticmain

但是,这种行为在 Java 7 中有所改变;现在您必须包含一个明确的main,即使它可能永远无法到达。

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


public class Test {
    static {
        System.out.println("Hello World");
        System.exit(0);
    }
}

爪哇 6:

你好世界

爪哇 7:

错误:在类Test中找不到主方法,请将主方法定义为:
   公共静态无效主要(字符串 [] 参数)
于 2013-07-26T19:16:36.607 回答
6

静态块在类初始化时执行。通常,main该类将导致引导类的初始化,但还有其他方法可以引导程序,例如通过 VM 的本机嵌入 API

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

  1. 创建该类的实例,
  2. 调用任何其他静态方法,
  3. 读取静态字段(非最终字段或具有原始类型或字符串以外的类型)。

有关更多详细信息,请参阅JLS 第 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上面一样。

于 2013-07-26T19:17:51.933 回答
1

在 java 8 中,如果不显式编写 main 方法,您将无法运行程序。从这个角度来看,答案是错误的。没有 main 方法,静态块不会执行。下面是一段代码,它显示了初始化的顺序。(静态块==>main==>初始化块==>构造函数)

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


在main 方法中的静态块中 在 const
中的初始化块中

于 2017-10-28T08:42:38.777 回答
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。

于 2018-06-16T17:54:30.017 回答
0

投票最多的答案是“大部分”正确,但不完全正确。考虑下面的代码,其中类有一个 main 方法和一个静态方法。静态方法将在 main 方法和构造函数之前执行(成功)并生成序列:ABCD - 这与您可能想象的不同。

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 ");
    }
}
于 2015-09-02T20:09:01.650 回答
-2

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

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

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

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

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

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

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

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

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

因为我已经告诉过它的编译器起着插入该字段的作用。请注意,找不到 main 方法是运行时错误,因此编译器对此不负责,而是 JVM 负责。

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

尽管在 java 7 中对 main 方法的探测是在执行静态块之前完成的,但静态块本身的执行取决于 main 方法的成功找到。即使程序的执行顺序是 program 与 java 6 和更早版本中的相同版。

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

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

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

于 2017-10-28T08:26:49.293 回答