反射方法多次调用构造函数

时间:2015-03-31 18:11:18

标签: java reflection javafx classloader javafx-8

我正在使用自定义类加载器和反射启动JavaFX GUI应用程序,但是我似乎无意中多次调用应用程序构造函数,这会引发异常(使用一种单例模式来保证没有人尝试重新启动 - 初始化主app类。)

当我从MyApp课程致电IllegalStateException时,startupMethod.invoke(instance);构造函数的Launcher被抛出。

public class MyApp extends Application {

    private static MyApp instance = null;

    private static boolean started = false;

    public MyApp() {
        if (instance != null) {
            throw new IllegalStateException("MyApp already initialized");
        }
        instance = this;
    }

    public static MyApp getInstance() {
        return instance;
    }

    public void startup() {
        synchronized (LOCK) {
            if (started == true) {
                throw new IllegalStateException("MyApp is already running");
            }
        }
       // do things to start the GUI, etc...
       //  ... ... ...
       started = true;
       launch(); // static method part of the JavaFX platform
    }

    @Override
    public void start(final Stage stage) {
        // do stuff to display GUI
    }

}

public class Launcher {

    public static void main(String[] args) {
        new Launcher().start();
    }

    private void start() {
        // create custom classloader ...
        // ... ... ...
        Class<?> myAppClass = myLoader.loadClass("com.something.MyApp");
        // calls the MyApp constructor and sets the "instance" static var to "this"
        Object instance = myAppClass.newInstance();

        Method startupMethod = myAppClass.getMethod("startup");
        // this seems to call the MyApp constructor again!, exception thrown...
        startupMethod.invoke(instance);
    }

}

如果我在MyApp构造函数中注释掉异常,应用程序启动就好了,但这意味着我仍然调用构造函数两次,我不确定为什么。我需要能够防止多次调用此构造函数的人。

EDIT:通过一些研究,似乎对静态方法Application.launch()的调用正在尝试在JavaFX应用程序线程上构建MyApp的新实例...

UPDATE:

通过向MyApp添加静态方法来修复,该方法只调用Application.launch()方法。从Launcher类我只需加载MyApp类,然后调用静态方法,如:

public class MyApp extends Application {
    public MyApp() {
        if (instance != null) {
            throw new IllegalStateException("Already initialized");
        }
        instance = this;
    }
    // other stuff
    public static void startup() {
        launch();
    }
}

public class Launcher {
    // other stuff
    Class<?> myAppClass = myLoader.loadClass("com.something.MyApp");
    Method startupMethod = myAppClass.getMethod("startup");
    startupMethod.invoke(null, null);
}

1 个答案:

答案 0 :(得分:1)

Application.launch()创建一个调用它的类的实例(必然是Application的子类)。这就是第二个实例的来源。