У меня проблема с Java FX и реализацией очень странного приложения. Позвольте мне показать это с помощью кода:
Представьте себе базовое приложение:
import javafx.application.Application;
import javafx.stage.Stage;
public class JavaFXApp extends Application {
// constructor, ...
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
// important stuff
initialize();
// important stuff
stage.show();
}
public void initialize() {
System.out.println("default");
// basically abstract
}
// and other functions.
}
и его расширение (как и предполагалось):
public class JavaFXAppExtended extends JavaFXApp {
// constructor, ...
@Override
public void initialize() {
System.out.println("extended");
}
}
Теперь вызов JavaFXApp не вызывает у меня никаких проблем. Но при вызове JavaFXAppExtended@Overwrite по сути игнорируется и вызывается initialize из родительского класса. Тем самым:
JavaFXApp.main(args);
-> default
JavaFXAppExtended.main(args);
-> default
при этом ожидалось «расширенное».
Почему initialize от родителя JavaFXAppExtended вызывается вместо @Overwrite?
Я пропустил что-то важное? Это незаконно? Я недостаточно опытен? Может это просто ошибка? Я не знаю. Но я хочу знать.




На самом деле JavaFXAppExtended.main(args) вызывает статический JavaFXApp.main, поскольку в JavaFXAppExtended нет main. В коде вызова JavaFXAppExtended не остается никаких следов. Точно такой же код, как JavaFXApp.main(args).
В статических функциях нет наследования this. Отсюда и название JavaFXApp.launch.
Ответ Йопа Эггена правильный, но я просто хочу добавить еще немного информации.
Метод launch(String..) представляет собой удобную перегрузку launch(Class,String...), когда класс приложения JavaFX и основной класс являются одним и тем же. Аргумент класса неявно является вызывающим классом. А класс вызывающего объекта — это класс, в котором объявлен вызывающий метод. В вашем вопросе классом вызывающего абонента является JavaFXApp, потому что именно там объявлен main и из него main вы звоните launch.
Платформа JavaFX берет класс приложения и создает его экземпляр. Затем он вызывает методы init, start и stop в соответствии с документированным жизненным циклом приложения JavaFX. Таким образом, в вашем вопросе объект, у которого вызван метод start, является экземпляром JavaFXApp, а не JavaFXAppExtended. Другими словами, переопределение initialize не игнорируется, скорее вы вызываете initialize для объекта, отличного от того, который вы ожидали.
Если вы хотите, чтобы JavaFXAppExtended был классом приложения, у вас есть два варианта:
Используйте launch(Class,String...), чтобы явно передать JavaFXAppExtended.class.
Вызовите launch(String..) из метода, объявленного в классе JavaFXAppExtended (это решение , которое вы выбрали ).
Обратите внимание: немного странно иметь две конкретные реализации Application в одном проекте. Возможно, JavaFXApp должен быть абстрактным и не содержать метода main. Или, если какой класс используется в качестве класса приложения, определяется каким-то условием времени выполнения, то, возможно, было бы лучше перенести этот выбор в другой основной класс. Например:
import javafx.application.Application;
public class Main {
// With this approach, neither application class should have a main method.
public static void main(String[] args) {
if (/* some condition */) {
Application.launch(JavaFXAppExtended.class, args);
} else {
Application.launch(JavaFXApp.class, args);
}
}
}
Действительно ценная справочная информация. И что немного странно иметь два приложения как таковых. Можно мыслить абстрактный базовый класс приложения.
Спасибо. Я пропустил добавление отдельного основного компонента в JavaFX Api Extended.