2017-03-28 109 views
0

我有以下功能傳遞類名作爲參數

public void loadWindowAndSendDataTest(String path, String appName, ConnectionData connectionData) { 
    try { 
     Stage subWindow = new Stage(); 
     subWindow.initModality(Modality.APPLICATION_MODAL); 
     FXMLLoader loader = new FXMLLoader(); 
     Parent parent = loader.load(getClass().getResource(path).openStream()); 
     ExitController exitController = (ExitController) loader.getController(); 
     exitController.getConnectionData(connectionData); 

     Scene scene = new Scene(parent); 

     subWindow.setScene(scene); 
     subWindow.setTitle(appName); 
     subWindow.show(); 
    } catch(IOException e) { 
     e.printStackTrace(); 
    } 

什麼,我想才達到是有更多的一般功能,我可以通過類名(在這種情況下ExitController),所以它會像這樣的:

public void loadWindowAndSendDataTest(String path, String appName, ConnectionData connectionData, String className) { 
    try { 
     Stage subWindow = new Stage(); 
     subWindow.initModality(Modality.APPLICATION_MODAL); 
     FXMLLoader loader = new FXMLLoader(); 
     Parent parent = loader.load(getClass().getResource(path).openStream()); 
     /* do sth with className to obtain UsedClassController class */ 
     UsedClassController usedClassController = (UsedClassController) loader.getController(); 
     usedClassControler.getConnectionData(connectionData); 

     Scene scene = new Scene(parent); 

     subWindow.setScene(scene); 
     subWindow.setTitle(appName); 
     subWindow.show(); 
    } catch(IOException e) { 
     e.printStackTrace(); 
    } 

假設是,我傳遞給這個函數的類已經實現了getConnectionData()功能。有沒有辦法做到這一點?

+0

調用這個好,你可以寫它具有一個接口方法'getConnectionData()',你以後可以檢查類名後面的類是否是該接口,然後你可以安全地調用它 –

+0

好吧,我看到了,但我怎麼能傳遞類名作爲參數,然後得到這個類內的函數做fe鑄件? –

+0

得到類對象:如果你有一個類(比如String),你可以使用'Class String.class';如果你有一個對象(比如說obj),你可以使用'Class obj.getClass()'.....來得到你可以在你的類對象上使用函數Class.getName()的名字,然後它就是一個字符串,再次將它轉換爲一個類,你可以使用'Class.forName(String)' –

回答

1

如果你假設控制器類有getConnectionData(ConnectionData)方法來實現,你可以只使用反射來調用該方法:

public void loadWindowAndSendDataTest(String path, String appName, ConnectionData connectionData) { 
    try { 
     Stage subWindow = new Stage(); 
     subWindow.initModality(Modality.APPLICATION_MODAL); 
     FXMLLoader loader = new FXMLLoader(); 
     Parent parent = loader.load(getClass().getResource(path).openStream()); 
     Object controller = loader.getController(); 
     Method getConnectionDataMethod = 
      controller.getClass().getMethod("getConnectionData", ConnectionData.class); 
     getConnectionDataMethod.invoke(controller, connectionData); 

     Scene scene = new Scene(parent); 

     subWindow.setScene(scene); 
     subWindow.setTitle(appName); 
     subWindow.show(); 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } 
} 

這不是一個特別強大或優雅的方法。也許更好的定義與getConnectionData方法的接口:

public interface ConnectionDataProvider { 

    public void getConnectionData(ConnectionData data) ; 

} 

,並有你的控制器執行該方法:

public class ExitController implements ConnectionDataProvider { 

    public void getConnectionData(ConnectionData data) { 
     // ... 
    } 

    // existing code ... 
} 

然後,你可以假設控制器是實現該方法的類:

public void loadWindowAndSendDataTest(String path, String appName, ConnectionData connectionData) { 
    try { 
     Stage subWindow = new Stage(); 
     subWindow.initModality(Modality.APPLICATION_MODAL); 
     FXMLLoader loader = new FXMLLoader(); 
     Parent parent = loader.load(getClass().getResource(path).openStream()); 
     ConnectionDataProvider controller = loader.getController(); 
     controller.getConnectionData(connectionData); 

     Scene scene = new Scene(parent); 

     subWindow.setScene(scene); 
     subWindow.setTitle(appName); 
     subWindow.show(); 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } 
} 

請注意,這些方法都不要求您傳入控制器的類型(類)。如果你真的需要,由於某種原因,你可以做以下(使用接口的方法):

public <T extends ConnectionDataProvider> void loadWindowAndSendDataTest(
     String path, String appName, 
     ConnectionData connectionData, Class<T> controllerType) { 

    try { 
     Stage subWindow = new Stage(); 
     subWindow.initModality(Modality.APPLICATION_MODAL); 
     FXMLLoader loader = new FXMLLoader(); 
     Parent parent = loader.load(getClass().getResource(path).openStream()); 
     T controller = loader.getController(); 

     // if you wanted to cast explicitly here, you could do: 
     // T controller = controllerType.cast(loader.getController()); 

     controller.getConnectionData(connectionData); 

     // do something with controllerType if you need.... 

     Scene scene = new Scene(parent); 

     subWindow.setScene(scene); 
     subWindow.setTitle(appName); 
     subWindow.show(); 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } 
} 

,然後你將與

loadWindowAndSendDataTest("/path/to/fxml", "Application Name", 
    connectionData, ExitController.class); 
1

您應該創建一個方法getConnectionData()的接口,在您的UsedClassController類中實現此接口。

要獲得班級名稱,請嘗試從班級對象中使用getSimpleName()。 BigDecimal示例:

BigDecimal.class.getSimpleName(); 

將返回BigDecimal。 如果你想獲得與包的名稱,你可以使用getCanonicalName()

+0

'String Class.getSimpleName()'不允許他將它轉換回來,因爲它缺少包,我建議使用'String Class.getName()' –

+1

我編輯了我的帖子,但是你的解決方案也沒問題 – Araneo