JavaFX运行时主方法
JavaFX的声明说: 当使用JavaFX Packager工具创建应用程序的JAR文件时,JavaFX应用程序不需要main()方法,该工具将JavaFX启动器嵌入JAR文件中。但是,包含main()方法非常有用,这样您就可以运行在没有JavaFX启动器的情况下创建的JAR文件,例如在使用未完全集成JavaFX工具的IDE时。此外,嵌入JavaFX代码的Swing应用程序需要main()方法 我尝试了这个方法,它是正确的,我可以不用JavaFX运行时主方法,java,javafx,Java,Javafx,JavaFX的声明说: 当使用JavaFX Packager工具创建应用程序的JAR文件时,JavaFX应用程序不需要main()方法,该工具将JavaFX启动器嵌入JAR文件中。但是,包含main()方法非常有用,这样您就可以运行在没有JavaFX启动器的情况下创建的JAR文件,例如在使用未完全集成JavaFX工具的IDE时。此外,嵌入JavaFX代码的Swing应用程序需要main()方法 我尝试了这个方法,它是正确的,我可以不用main方法启动我的应用程序 但是,当我从应用程序类中声明一个
main
方法启动我的应用程序
但是,当我从应用程序
类中声明一个main
方法调用launch
时,程序仍然有效。
的文档说,JavaFX运行时正在创建应用程序
类的实例,并调用init
方法
但是JavaFX运行时是如何启动的呢?我的意思是,必须有一个
main
方法才能启动一切。所以我想知道我是否自己声明了一个main
方法,不是有两个吗?一个可能的答案可能是,在应用程序中声明了一个main
方法。如果从Application
扩展的另一个类有自己的main
方法,则该代码仍然有效,并且Application
的main
方法将被忽略:
class Main extends OtherMain {
public Main(String text) {
System.out.println(text);
}
/* If this method is removed, the main-method is called from OtherMain */
public static void main(String[] args) {
new Main("Called from Main-Class");
}
}
class OtherMain {
public static void main(String[] args) {
new Main("Called from Other-Main-Class");
}
}
这有意义吗?实际上,我一直对Java如何启动JavaFX应用程序感兴趣,所以我决定调试这个过程。在回答剩下的问题之前,先做一些事情:
- 我用JDK-10为一个独立的桌面应用程序进行了调试。快速浏览一下JDK-11源代码,就可以看出该过程在不同版本之间没有改变
- 当我使用
Application
时,我指的是javafx.Application.Application
类
- 当我使用“
main
method”时,我指的是publicstaticvoidmain(String[]args)
方法。类似地,“main类”指包含main
方法的类
- 源代码的所有链接都指向OpenJDK Mercurial存储库
- 实际上,所有这些都是实施细节,可能会在不另行通知的情况下进行更改
总结
启动JavaFX应用程序时,如果主类是应用程序的子类
,则Java启动器使用自己的内部主类。这个内部类负责初始化JavaFXToolkit。一旦工具箱初始化,就会发生以下两种情况之一
应用程序子类具有main
方法。
- 在本例中,一些内部JavaFX代码调用
main
方法。现在,开发人员负责通过application.launch
完成应用程序的启动
应用程序子类没有main
方法。
- 在本例中,相同的内部JavaFX代码启动应用程序本身。第一个案例最终在与本案例相同的地方结束
基本上,在Application
子类中声明的任何main
方法都不是“正常的”main
方法。想象一下这样的行为:
- 内部
main
方法充当Java应用程序的入口点,就像所有“普通”main
方法一样
Application
subclass'main
方法作为JavaFX应用程序的可选入口点,其中JavaFX工具包已经初始化
详细答案
首先,您并不是“覆盖”应用程序
类的main
方法;应用程序
类没有main
方法。实际上,只要应用程序声明的主类是application
的子类,Java就会使用自己的主类。对于后代,可以使用以下方法之一声明主类:
- 在命令行(文件)上指定它:
java-cp foo.Main
- 在命令行(模块)上指定它:
java-p-mfoo/foo.Main
- 在JAR清单中指定它:
Main类:foo.Main
- (另一种方式我忘记了?)
台阶
这些步骤假设是一个JavaFX应用程序。如果启动一个“常规”Java应用程序,大多数情况都不会发生
步骤1:加载主类
内部类LaunchHelper
,通过名为checkAndLoadMain
的方法检查并加载主类。此方法负责根据主类的声明方式(如上所述)解析主类。一旦找到,此方法将检查主类是否是应用程序的子类。如果是,则主类将更改为静态内部类:launchelper$FXHelper
。然后执行一些验证,并将类
返回到本机代码
相关代码:
步骤2:调用main
方法
在发现、加载和验证主类之后,将从(我假设)本机代码调用它。由于我们讨论的是JavaFX应用程序,现在的主要类是launchelper$FXHelper
。这个类的main
方法做了一件简单的事情:通过反射调用内部JavaFX代码
相关代码:
步骤3:JavaFX预启动
步骤2调用的代码位于名为launchempl
的类中;具体来说,启动应用程序(String,String,String[])
方法。此方法的作用似乎与launchelp类似
// main class
public class Main {
public static void main(String[] args) {
Application.launch(App.class, args);
}
}
// JavaFX Application class
public class App extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
// setup and show primaryStage
}
}