[英]Exception handling in static initializer
通常我通過顯示一些帶有詳細信息的自定義警報 (JavaFX) 來處理我的異常,但是當我的類的靜態初始化程序運行時,JavaFX 運行時根本沒有初始化。
有沒有辦法處理這種異常而不像動物一樣打印其內容?
public class MyStaticInitializedClass {
static {
try {
//do the things that may throw exception
} catch(Exception ex) {
ExceptionHandler.showException(ex);
}
}
}
public class ExceptionHandler {
public static void showException(Exception ex) {
//constructs JavaFX alert with exception details
alert.show();
}
}
首先考慮是否不應該讓應用程序簡單崩潰並記錄原因。 靜態初始化程序中的失敗通常意味着環境存在嚴重問題,您不太可能從中恢復。 另外,據我所知,一旦一個類加載失敗,它就不能再被同一個ClassLoader
。
也就是說,如果您想在警報中向用戶顯示錯誤,即使錯誤發生在 JavaFX 運行時初始化之前,您也需要將錯誤保存在某處。 然后,一旦您啟動 JavaFX,請檢查您存儲錯誤的位置並顯示它們。 例如:
主.java:
import javafx.application.Application;
public class Main {
public static void main(String[] args) {
// an "error" before JavaFX is launched
App.notifyUserOfError(new RuntimeException("OOPS!"));
Application.launch(App.class, args);
}
}
應用程序.java:
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayDeque;
import java.util.Objects;
import java.util.Queue;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class App extends Application {
private static Queue<Throwable> errorQueue;
private static App appInstance;
public static synchronized void notifyUserOfError(Throwable throwable) {
Objects.requireNonNull(throwable);
if (appInstance == null) {
if (errorQueue == null) {
errorQueue = new ArrayDeque<>();
}
errorQueue.add(throwable);
} else {
if (Platform.isFxApplicationThread()) {
appInstance.showErrorAlert(throwable);
} else {
Platform.runLater(() -> appInstance.showErrorAlert(throwable));
}
}
}
private static synchronized Queue<Throwable> setAppInstance(App instance) {
if (appInstance != null) {
throw new IllegalStateException();
}
appInstance = instance;
var queue = errorQueue;
errorQueue = null; // no longer needed
return queue;
}
private Stage primaryStage;
@Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
var scene = new Scene(new StackPane(new Label("Hello, World!")), 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
var errors = setAppInstance(this);
if (errors != null) {
// if non-null then should be non-empty
do {
showErrorAlert(errors.remove());
} while (!errors.isEmpty());
// possibly exit the application if you can't recover
}
}
private void showErrorAlert(Throwable error) {
var alert = new Alert(AlertType.ERROR);
alert.initOwner(primaryStage);
alert.setContentText(error.toString());
var sw = new StringWriter();
error.printStackTrace(new PrintWriter(sw));
var area = new TextArea(sw.toString());
area.setEditable(false);
area.setFont(Font.font("Monospaced", 12));
var details = new VBox(5, new Label("Stack trace:"), area);
VBox.setVgrow(area, Priority.ALWAYS);
alert.getDialogPane().setExpandableContent(details);
alert.showAndWait();
}
}
如果 JavaFX 尚未初始化,則上面將錯誤放入隊列中。 在start
方法結束時,檢查隊列是否有任何錯誤,並將它們一個接一個地顯示給用戶。 如果 JavaFX 已經被初始化,那么錯誤會立即顯示給用戶。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.