将类名作为参数传递

时间:2017-03-28 11:40:04

标签: java javafx

我有以下功能

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();
    }

假设传递给此函数的I类已实现getConnectionData()功能。有没有办法做到这一点?

2 个答案:

答案 0 :(得分:1)

您应该使用方法getConnectionData()创建一个接口,在UsedClassController类中实现此接口。

要获取类的名称,请尝试使用类对象中的getSimpleName()。 BigDecimal的示例:

 BigDecimal.class.getSimpleName();

将返回BigDecimal。 如果您想使用包获取名称,可以使用getCanonicalName()

答案 1 :(得分:1)

如果您假设控制器类已实现.git/hooks方法,则可以使用反射来调用该方法:

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();
    }
}