17

我在 Java 中有以下简单的 hello world:

class A {
    static {
        System.out.println("Hello world");
    }
}

它按预期工作,但奇怪的是,它给出了一个错误,说明 main 方法之后不存在。

$ javac A.java && java A
Hello world
Exception in thread "main" java.lang.NoSuchMethodError: main

为什么?我应该忽略它吗?我什至尝试制作一个名为“main”的方法,但它没有任何改变。

class A {
    static {
        main();
    }
    public static void main() {
        System.out.println("Hello world");
    }
}

$ javac A.java && java A
Hello world
Exception in thread "main" java.lang.NoSuchMethodError: main
4

6 回答 6

24

当你的类被加载时,static初始化程序将被运行,然后 JVM 将尝试调用该main方法。static您可以通过在初始化程序中再添加一行来解决此问题:

public class HelloWorld {
    static {
        System.out.println("Look ma', no hands!");
        System.exit(0);
    }
}

这将在 JVM 尝试调用您的main方法之前停止它。

另请注意,这不会在 Java 7 中执行。Java 7main在初始化类之前会查找方法。

于 2013-07-05T21:07:19.980 回答
11

这是因为您的类是由类加载器加载的,静态代码被执行,然后它搜索 main 方法并由于它不存在而崩溃。

包裹在任何方法之外的静态块中的类中的代码将在第一次引用该静态类时执行。

它找不到您的主要方法的原因是您错误地声明了它。主要看起来像这样:

public static void main(String[] args){}

习惯那条线。你会看到很多很多次。

String[] args... 参数是用户可以通过 shell 传递给您的程序的以空格分隔的参数列表。所有程序都通过main方法进入。这是一个流传了一段时间的标准。

可以在类中使用静态块来启动您的程序,但它会引起混乱并且非常不合适。使用主要方法作为切入点是行业标准。

我无法给出为什么这是标准的原因,或者给出一个更令人信服的论点来说明为什么要使用它,而不是从 shell 输入你的程序。我不建议从静态块开始你的程序。

于 2013-07-05T21:05:18.827 回答
8

忘记static块,像这样做:

public static void main(String[] args) {
    System.out.println("Hello, world!");
}
于 2013-07-05T21:09:17.300 回答
5

你确实需要一个main方法。在上一个代码示例中,您定义错误。像这样定义它:

public static void main(String[] args) {

}

你错过了args这就是为什么它仍然第二次抱怨。

@WilliamMorrison 和@Jeffrey 解释了为什么你的程序输出“Hello world”然后它崩溃了。

有一个很好的理由使用main而不是使用static块的方式。主要是,它是您程序的入口点。没有一个,您将无法从java命令成功运行您的程序。没有一个 jar 文件就无法执行。而且,正如您所看到的,如果您缺少主要内容,您每次都会收到此错误,除非您编写一个黑客来防止它(请参阅@Jeffrey 的回答。我并不是说在进攻中方式,他的回答非常翔实,但它是一个 hack IMO)。

另一件事是,这不是惯用的。如果我必须阅读您的代码,我会想,“这个该死的代码从哪里开始?!” 我无法下载它并弄清楚如何让我的工具(IDE、maven、ant 等)运行它。Intellij 不知道它可以在没有方法的情况下运行一个类main。这是程序的标准入口点。

随机static块不是入口点。没有办法将参数传递给它。例如,如果你想编写一个像 unix 的“cat”这样的命令行程序,你传入一个文件名并输出文件内容,你不能用static块来做,因为没有办法设置和获取输入。

于 2013-07-05T21:05:39.313 回答
2

它按预期工作,但奇怪的是:没有类被加载。当一个类被加载时,它的静态块就会被执行。

为什么你得到Exception in thread "main" java.lang.NoSuchMethodError: main

因为在第一种情况下您没有主要方法,而在第二种情况下签名不正确。

将其更改为public static void main(String a[])

于 2013-07-05T21:06:25.433 回答
1

当类加载到 JVM 时,它首先“处理”静态块中的内容,这就是它首先打印出“Hello World”的原因,这解释了这部分:

class A {
    static {
        System.out.println("Hello world");
    }
}

当您运行程序时,它会查找“main”方法,因此它会打印出第Hello World一个然后查找 main 方法,因此错误,当您在静态块内调用该方法时应用相同的逻辑。

于 2013-07-24T08:13:22.117 回答