如何通过注释访问JavaFX字段?

如何通过注释访问JavaFX字段?,java,javafx,annotations,Java,Javafx,Annotations,我想做的是: 我有一个使用JavaFX的Java程序。我创建了一个fxml文件,在其中创建了JavaFx控制器,然后在AddEmployeeOrderController类中声明。我想将这些创建的控制器字段传输到POJO。因为我认为这非常耗时,并且会导致很多粗心的错误,所以我想更自动化这个过程。我的想法是为每个声明的JavaFX控制器字段创建一个注释,这样,例如,在另一个方法中,只要按下一个按钮,就可以自动检索所有带注释的字段。因此,您可以通过这种方式理解它,而不是自己手写所有内容,例如: Em

我想做的是: 我有一个使用JavaFX的Java程序。我创建了一个fxml文件,在其中创建了JavaFx控制器,然后在AddEmployeeOrderController类中声明。我想将这些创建的控制器字段传输到POJO。因为我认为这非常耗时,并且会导致很多粗心的错误,所以我想更自动化这个过程。我的想法是为每个声明的JavaFX控制器字段创建一个注释,这样,例如,在另一个方法中,只要按下一个按钮,就可以自动检索所有带注释的字段。因此,您可以通过这种方式理解它,而不是自己手写所有内容,例如:

EmployeeDto employeeDto = new EmployeeDto(textfield.getText(), textfield2.getText()..);
我首先创建了AddEmployeeOrderController,声明了一些JavaFX字段,并添加了一个注释。在AddEmployeeOrderController类中,我再次尝试访问带注释的字段

然后,从逻辑上讲,我必须将java.lang.reflect.Field转换为JavaFXTextField,但这显然是不可能的。它只抛出IllegalArgumentException错误,当然,这是因为您不能将java.lang.reflect.Field强制转换为JavaFX文本字段

是否有一种方法可以通过注释来实现我的想法,或者我被迫手工编写所有内容并生成所谓的样板代码

 public class AddEmployeeOrderController implements Initializale {
     @FXML
     @MyAnno
     public TextField orderDateFromTextField;

     public void atPushButton() {
         for (Field field : AddEmployeeOrderController.class.getDeclaredFields()) {
             if (field.isAnnotationPresent(MyAnno.class)) {
                 if (((Field) object).getType().getCanonicalName()
                                               .contains("TextField")) {
                     TextField textField = (TextField) field.get(this);
                     textField.getText();
                 }
             }
         }
     }
 }

 @Retention(RetentionPolicy.RUNTIME)
     public @interface MyAnno {
 }

您没有提供足够的相关代码来理解您实际在做什么。然而,我们可以推断如下:

您正在使用的字段类是java.lang.reflect.Field

根据,应该使用对实例的引用调用Field.getObject。。。或空。如果提供了实例,那么它需要是声明字段的类的实例或该类的子类

如果使用非必需类的参数调用Field.get,则会引发IllegalArgumentException

所以。。。如果你告诉我们并向我们展示的是正确的。。。这不是要传递给Field的正确对象。请访问该Field对象

您的意思是,您向我们展示的字段反射代码位于AddEmployeeController类中。这意味着这将是一个AddEmployeeController实例。但是您正在迭代的字段实例是由类AddEmployeeOrderController声明的字段。因此,您应该使用引用AddEmployeeOrderController实例的非null值调用get。或者,您应该迭代AddEmployeeController的声明字段。如果没有更多的上下文,就很难说正确的修复方法是什么

如果我们去掉所有动态/反射的东西,那么您的代码所做的与此非反射代码类似:

public class AddEmployeeOrderController {
    public TextField someField; 
}

public class AddEmployeeController {
    public void someMethod() {
        TextField t = (TextField)(this.someField);
    }
}
它不会编译,因为AddEmployeeController没有名为someField的字段

实际上,您需要做的是类似的:

public class AddEmployeeController {
    public void someMethod(AddEmployeeOrderController aeoc) {
        TextField t = (TextField)(aeoc.someField);
    }
}   
只是想澄清一下,问题并不是来自输入的类型转换

(TextField) field.get(this);
如果类型转换失败,那么异常将是ClassCastException。您看到的异常来自get调用

问题不在于注释

后续行动

我已经完成了您尝试的MRE,分析了JavaFX的内容,并将其转化为工作代码。我的版本展示了如何通过匹配字段的类型和注释来反射地提取字段值

package test;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
}

// End of MyAnno

package test;
import java.lang.reflect.Field;

public class MyTest {
    @MyAnno
    public String someField = "Hi Mom";
    
    public void doIt() throws Exception {
        for (Field field : this.getClass().getDeclaredFields()) {
            if (field.isAnnotationPresent(MyAnno.class)) {
                if (field.getType().getCanonicalName().equals("java.lang.String")) {
                    String value = (String) field.get(this);
                    System.out.println(value);
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        new MyTest().doIt();
    }
}
请注意,这是真实的代码。它编译、运行和。。。作品试试看。若您将字符串改为TextField,则可以根据您的问题对其进行调整。该领域的实际类型几乎与核心问题完全无关。如你所见

可以改进和简化的一件事是,类型测试应该使用Class.equals,而不是测试类的名称。它更干净、更可靠

您的一个担忧是,我认为您需要大量的样板代码来解决您的问题。我认为情况并非如此:

如果我为MyTest声明一个抽象超类并将doIt的实现放在那里。。。它应该会起作用。请注意,doIt使用this.getClass获取当前对象的类

如果doIt在一个不相关的类中,如果该方法有一个传递目标对象的参数,那么它也可以工作

甚至可以根据字段的类型对其进行参数化。或者查找属于给定类型的子类型的字段。等等提示:您需要将类型作为类对象传递

我说尝试MRE是有原因的。事实上,您的代码没有编译。实际上,您有一个未声明的变量对象,其预期类型和用途很难理解。我认为这是一个错误,并猜测您的意图是使用该字段。但我不应该猜

真正的MRE需要完整且可编译,除非您的问题是如何编译它。理想情况下,它也应该是可运行的,并且运行MRE应该重现问题 你问的是他们


关键是,我们这些试图帮助您的人需要确保我们了解您的问题所在。这就是MRE的目的。

你能解释一下你的煤到底是什么吗?你想用这个机制实现什么?从这里开始->你为什么要做Object=field;如果你所做的只是立即将其抛回场上?只需使用字段引用。如果你想从控制器实例中获取字段的值,那么你需要将控制器实例传递给Fieldget….是的,‘Object Object=field’;是过时的,是我以前尝试的一些遗留物。但据我所知,‘texfield textfield=textfield.getorderDateFromTextField’可以吗?因为我不这么认为,它会产生同样的异常。AddEmployeeOrderController控制器=。。。;。现在您有了控制器类的一个实例。从实例类中获取字段,然后调用Object value=theField.getcontroller。但是,请确保控制器引用的实例或您使用的任何字段/变量都与UI使用的实例相同。是的,您所说的一切都是正确的,只是我的问题,也是我的目标,正如我写的那样:通过注释传递TextField,然后通过注释传递TextField,例如,通过注释传递TextField上的getText,与我在AssEmployeeController类中声明的完全相同。正如您所说,正如我所说,是否不可能将java.lang.reflect.Field强制转换为TextField JavaFX。。?那么,还有一种可能性是什么呢?我必须利用注释!如果我更新的答案对你来说仍然没有意义,请用a更新问题,这样我们就可以准确地看到你在做什么。再次感谢你的关注,我已经重写了我的问题,希望这不是问题。相信现在应该是我努力实现的目标。是的。我看你已经做到了。我相信这不会使我在回答中写的任何东西无效,而且。。。的确如果你明白了,我的回答会帮助你解决我的问题。然而,我认为我们能够说服您的唯一方法是,如果您编写一个最小的可复制示例。@Koala阅读参考的帮助页面并相应地采取行动