简体   繁体   English

传递类名作为参数

[英]Passing class name as a parameter

I have following function 我有以下功能

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

And what I'd like to achive is to have more general function where I can pass class name (in this case ExitController), so it would like something like this: 我想实现的是具有更通用的功能,可以在其中传递类名(在本例中为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();
    }

The assumption is that the class I'm passing to this function have getConnectionData() fuction implemented. 假设是我传递给此函数的类已实现getConnectionData()功能。 Is there a way to do this? 有没有办法做到这一点?

You should create an interface with method getConnectionData() , implement this interface in your UsedClassController class. 您应该使用getConnectionData()方法创建一个接口,并在UsedClassController类中实现此接口。

To get name of the class try to use getSimpleName() from class object. 要获取类的名称,请尝试从类对象使用getSimpleName() Example for BigDecimal: BigDecimal的示例:

 BigDecimal.class.getSimpleName();

will return BigDecimal . 将返回BigDecimal If you want to get the name with package, you can use getCanonicalName() 如果要使用包获取名称,则可以使用getCanonicalName()

If you're assuming the controller class has the getConnectionData(ConnectionData) method implemented, you could just use reflection to invoke that method: 如果假设控制器类实现了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();
    }
}

This isn't a particularly robust or elegant approach. 这不是一个特别健壮或优雅的方法。 Perhaps better is to define an interface with the getConnectionData method: 也许更好的方法是使用getConnectionData方法定义一个接口:

public interface ConnectionDataProvider {

    public void getConnectionData(ConnectionData data) ;

}

and to have your controllers implement that method: 并让您的控制器实现该方法:

public class ExitController implements ConnectionDataProvider {

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

    // existing code ...
}

Then you can just assume the controller is from a class implementing that method: 然后,您可以假设控制器来自实现该方法的类:

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

Note that neither of these approaches requires you to pass in the type (class) of the controller. 请注意,这两种方法都不要求您传入控制器的类型(类)。 If you really needed that for some reason, you could do the following (using the interface approach): 如果由于某些原因确实需要这样做,则可以执行以下操作(使用接口方法):

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

and then you would invoke this with 然后您可以使用

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM