我有以下代码。
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
语句中的条件转换为失败的条件,并且我肯定在调试器中看到它不执行launch
方法,但是仍然显示应用程序窗口
我还注意到,在return
方法内使用main
语句无效-应用程序仍继续执行。它仅响应System.exit(0)
。
为什么会这样?
更新:
根据您的要求,这是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文件,但会访问复杂的档案,这就是为什么我已经创建了几种几乎相同的方法的原因。
Utility.load
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;
}
}
只需反序列化文件中的对象即可。
答案 0 :(得分:1)
从我假设您调用launch(args)
的方式开始,后来您confirmed假设,main
方法位于Application
的子类中。我相信这是造成您问题的原因。
您已经注意到,有很多看似JavaFX的线程正在运行。具体来说,非守护程序“ JavaFX Application Thread”正在运行(至少,在Java 10中是非守护程序)。即使main
线程退出,该线程也将导致JVM保持活动状态。这是Java的正常行为:
java.lang.Thread
Java虚拟机启动时,通常只有一个非守护线程(通常调用某些指定类的名为
main
的方法)。 Java虚拟机将继续执行线程,直到发生以下两种情况之一为止:
- 已调用类
exit
的{{1}}方法,并且安全管理器已允许进行退出操作。- 不是所有守护进程线程的所有线程都已死亡,要么通过从调用返回到
Runtime
方法,要么抛出传播到run
方法之外的异常。
但是,当您故意还没有调用run
时,为什么启动了“ JavaFX Application Thread”呢?我只是在这里猜测,但这可能与JavaFX应用程序获得的特殊待遇有关。至少从Java 8开始,您不必在Application.launch
1 的子类中声明main
方法。如果主类是Application
的子类,则Java将自动处理启动。
Application
如果具有上述条件,并调用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
会覆盖启动JavaFX应用程序的默认行为,但不会阻止JavaFX运行时的初始化。也许这种行为是设计使然,或者是疏忽大意。但是重要的是,这仅在主类具有main
方法并且是main
子类的情况下才会发生。如果您将两者分开:
Application
那么您将不再有此问题。
否则,您可以继续使用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()
之前,您似乎正在main
方法中执行初始化。如果在初始化期间出现问题,则要中止启动JavaFX应用程序。好吧,JavaFX提供了自己执行此操作的方法:Application.init()
。
应用程序初始化方法。加载并构造Application类后,立即调用此方法。在实际启动应用程序之前,应用程序可以重写此方法以执行初始化。
Application类提供的此方法的实现不起作用。
注意:JavaFX应用程序线程上未调用此方法。应用程序不得使用此方法构造场景或舞台。应用程序可以使用此方法构造其他JavaFX对象。
将初始化代码移至此方法。如果您调用Platform.exit()
,则该应用程序将退出,并且不会调用Application.launch
。一种替代方法是在Application.start
中引发异常。您还可以使用Application.getParameters()
来获取应用程序参数,该参数返回Application.Parameters
的实例。
init
1。 Java SE在版本8中包含JavaFX。请注意,由于JavaFX将再次与Java SE分开,因此在Java 11中此行为可能会更改。