2015-03-31 70 views
2

我正在使用自定義類加載器和反射啓動JavaFX GUI應用程序,但是我似乎無意中調用了多次應用程序構造函數,這會引發異常(使用某種單例模式以確保沒有人嘗試重新初始化主要的應用程序類)。反射方法調用構造函數多次

MyApp構造函數的IllegalStateException在我從Launcher類中調用startupMethod.invoke(instance);時拋出。

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()試圖打造MyApp JavaFX應用程序線程上一個新的實例...

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

'launch()'爲你創建一個實例。 – 2015-03-31 18:43:44

+0

@James_D yep,只是通過調用一個靜態方法來調整'Application.launch()'來解決這個問題。謹慎地把這個答案放在一個答案中,以便我可以標記爲正確的? – SnakeDoc 2015-03-31 18:47:45

回答

1

Application.launch()創建在其上,它被稱爲類(不一定是的Application子類)的一個實例。這是第二例來自的地方。