簡體   English   中英

傳遞類名作為參數

[英]Passing class name as a parameter

我有以下功能

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()功能。 有沒有辦法做到這一點?

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

要獲取類的名稱,請嘗試從類對象使用getSimpleName() BigDecimal的示例:

 BigDecimal.class.getSimpleName();

將返回BigDecimal 如果要使用包獲取名稱,則可以使用getCanonicalName()

如果假設控制器類實現了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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM