为什么javafx忽略main的返回,仍然启动应用程序?
我有以下代码为什么javafx忽略main的返回,仍然启动应用程序?,java,javafx,return,main,Java,Javafx,Return,Main,我有以下代码 public static void main(String[] args) { if (!ArgumentsHandler.handle(args)) { return; } Storage.getInstance().load(); if (!Storage.getInstance().isLoadSuccessful()) { launch(args); } else
public static void main(String[] args)
{
if (!ArgumentsHandler.handle(args))
{
return;
}
Storage.getInstance().load();
if (!Storage.getInstance().isLoadSuccessful())
{
launch(args);
}
else
{
System.err.println("Unable to load configurations.");
}
}
我已经明确指出if语句中的条件使其失败,并且我可以在调试器中清楚地看到它没有执行启动方法,但应用程序窗口仍在显示
我还注意到,在main方法中使用return语句没有任何效果——应用程序仍然继续执行。它只响应System.exit0
为什么会这样
更新:
按照您的要求,这里是ArgumentsHandler的一个片段。在这里,我没有使用线程,至少是有意的
public static boolean handle(String[] args)
{
//handle args
if (args.length > 0)
{
switch (args[0])
{
//createRepository
case "-c":
configure(args);
break;
case "-r":
case "--repository":
repository(args);
break;
default:
help();
break;
}
return false;
}
return true;
}
private static void configure(String[] args)
{
if (args.length > 1)
{
boolean isRandom = false;
switch (args[1])
{
case "true":
case "1":
isRandom = true;
break;
case "false":
case "0":
//valid input, ignored
break;
default:
System.err.println("Invalid arguments. Possible values: [--configuration] [1/0].");
return;
}
Storage.configure(isRandom); //creates a bunch of json files (uses NIO).
return;
}
else
{
System.err.println("Invalid arguments. Possible values: -c [1/0].");
}
}
储藏
public void load()
{
isLoadSuccessful = false;
//load configuration
app = loadConfiguration(appFilePath);
if (app == null)
{
System.err.println("Unable to load app configuration.");
return;
}
//load company
company = loadCompany(app.getCompanyFilePath());
if (company == null)
{
System.err.println("Unable to load company configuration.");
return;
}
repository = loadRepository(app.getRepositoryFilePath());
if (repository == null)
{
System.err.println("Unable to load repository configuration.");
return;
}
isLoadSuccessful = true;
}
private static App loadConfiguration(String filePath)
{
return (App) Utility.load(filePath, App.class);
}
loadConfiguration、loadCompany和loadRepository实际上是相同的。将来,它们不会读取简单的json文件,而是访问复杂的归档文件,这就是为什么我已经创建了几个几乎相同的方法
公用事业负荷
public static Object load(String path, Type type)
{
try
{
JsonReader reader = new JsonReader(new FileReader(path));
Gson gson = new Gson();
Object obj = gson.fromJson(reader, type);
reader.close();
return obj;
}
catch (IOException ex)
{
ex.printStackTrace();
return null;
}
}
只是从文件中反序列化对象。根据您调用launchargs的方式,我假设,稍后您会看到,main方法位于应用程序的子类中。我相信这就是你问题的原因 正如您所注意到的,有许多看似特定于JavaFX的线程正在运行。具体地说,非守护进程JavaFX应用程序线程正在运行,至少在Java10中是非守护进程。即使主线程退出,该线程也会使JVM保持活动状态。这是Java的正常行为: java.lang.Thread 当Java虚拟机启动时,通常有一个非守护进程线程,该线程通常调用某个指定类的main方法。Java虚拟机将继续执行线程,直到发生以下任一情况: 类运行时的exit方法已被调用,并且安全管理器已允许执行exit操作。 所有不是守护进程线程的线程都已死亡,要么是通过调用run方法返回,要么是通过抛出传播到run方法之外的异常。 但是,为什么JavaFX应用程序线程在您故意不调用Application.launch的情况下启动呢?我只是在这里猜测,但这可能与JavaFX应用程序收到的特殊待遇有关。至少在Java8中,您不必在Application1的子类中声明main方法。如果主类是应用程序的子类,Java将自动处理启动
import javafx.application.Application;
import javafx.stage.Stage;
public class MyApp extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
// create scene and show stage...
}
}
如果您具有上述功能并调用java MyApp,则应用程序将启动并调用start。但是,如果您具备以下条件:
import javafx.application.Application;
import javafx.stage.Stage;
public class MyApp extends Application {
public static void main(String[] args) {}
@Override
public void start(Stage primaryStage) throws Exception {
// create scene and show stage...
}
}
然后调用main方法,但不调用start。基本上,显式声明main会覆盖启动JavaFX应用程序的默认行为,但不会阻止初始化JavaFX运行时。也许这种行为是故意的,也可能是疏忽。但这里重要的是,只有当主类有一个main方法并且是一个应用程序子类时,才会发生这种情况。如果将这两者分开:
public class MyApp extends Application {
// implement ...
}
public class Main {
public static void main(String[] args) {
// Perform pre-checks, return if necessary
Application.launch(MyApp.class, args);
}
}
那么你就不会再有这个问题了
否则,您可以继续使用System.exit或切换到Platform.exit
还有另一种可能更合适的方法来处理这个问题。在调用Application.launch之前,您似乎正在主方法中执行初始化。如果在初始化过程中出现问题,您希望中止启动JavaFX应用程序。好的,JavaFX本身提供了实现这一点的方法:
应用程序初始化方法。加载和构造应用程序类后,立即调用此方法。应用程序可以重写此方法,以便在实际启动应用程序之前执行初始化
应用程序类提供的此方法的实现不起任何作用
注意:此方法不在JavaFX应用程序线程上调用。应用程序不得在此方法中构造场景或舞台。应用程序可以在此方法中构造其他JavaFX对象
将初始化代码移到此方法。如果调用,则应用程序将退出,并且不会调用application.start。另一种方法是在init内部抛出异常。还可以使用返回的实例来获取应用程序参数
一,。JavaFX在版本8中包含在JavaSE中。注意,由于JavaFX将再次与JavaSE分离,Java11中的这种行为可能会发生变化。请您展示ArgumentsHandler.handle的代码片段。。。和存储。加载?我假设这些方法中的一个产生了一个非守护进程线程,该线程阻止进程在离开主方法后结束。从主线程调用主方法,只是因为返回并不意味着退出线程。您没有足够的进度来启动窗口,但是也没有明确地告诉线程退出,因此您会遇到应用程序暂停。我不确定您在main方法中试图做什么,但是如果您试图返回,那么您可能无论如何都想退出。@tryl
问题中添加了imits。您可以在调试时检查除主线程外是否还有其他线程在运行。如果使用Eclipse,您可以在Debug视图中看到正在运行的线程:从调用launch的方式来看,我假设main位于应用程序子类中。我发现在应用程序类中使用main会导致某种初始化,从而在main退出后阻止JVM退出。尽管未调用launch,但仍会发生这种情况。我猜这与Java启动JavaFX应用程序的特殊方式有关,因为将main移到另一个类不会导致这个问题。它不是由应用程序类引起的,因为手动初始化该类也不会导致此问题。
public class MyApp extends Application {
@Override
public void init() throws Exception {
if (!ArgumentsHandler.handle(getParameters()) {
Platform.exit(); // or throw an exception
} else {
Storage storage = Storage.getInstance();
storage.load();
if (!storage.isLoadSuccessful()) {
Platform.exit(); // or throw an exception
}
}
}
@Override
public void start(Stage primaryStage) throws Exception {
// Create Scene and show the primary Stage
}
@Override
public void stop() throws Exception {
/*
* Called when the JavaFX application is exiting, such as from
* a call to Platform.exit(). Note, however, that in my experience
* this method is *not* called when Platform.exit() is called inside
* the "init" method. It is called if Platform.exit() is called from
* inside the "start" method or anywhere else in the application once
* it is properly started.
*
* This is where you could perform any necessary cleanup.
*/
}
}