使用Java反射调用FXMLLoader命名空间put方法报错排查求助
问题原因分析
FXMLLoader的namespace返回的是由FXCollections创建的ObservableMap实例,这类实例通常是JavaFX内部的包装类(比如ObservableMapWrapper),它并没有自己声明put(String, Person)方法——这个方法是从Map接口继承来的。
你用getDeclaredMethod()方法查找时,该方法只会查找当前类自己声明的方法,不会包含继承自父类或接口的方法,所以会抛出方法未找到异常。
解决方案
方案1:通过父接口Map获取方法
直接从Map接口中获取put方法,因为所有Map实现类都继承并实现了这个方法:
// 获取Map接口的put方法 Method putMethod = Map.class.getMethod("put", Object.class, Object.class); // 调用方法,传入namespace实例、键、值 putMethod.invoke(FXMLLoader.getNamespace(), "personname", personObject);
如果需要严格匹配参数类型(String和Person),可以用getMethod的重载,但因为Map的put方法参数是Object, Object,直接用这个即可,反射调用时会自动适配。
方案2:获取ObservableMap的实际委托对象(不推荐)
如果一定要调用包装类内部的put方法,可以尝试获取它委托的原始Map实例(依赖JavaFX内部实现,不同版本可能失效):
// 获取包装类的内部map字段 Field mapField = FXMLLoader.getNamespace().getClass().getDeclaredField("map"); mapField.setAccessible(true); Map<String, Object> delegateMap = (Map<String, Object>) mapField.get(FXMLLoader.getNamespace()); // 直接调用delegateMap的put方法(或继续用反射) delegateMap.put("personname", personObject);
方案3:避开反射(最推荐)
既然ObservableMap本身就是Map的子接口,直接强转后调用put方法即可,完全不需要反射:
((Map<String, Person>) FXMLLoader.getNamespace()).put("personname", personObject);
内容的提问来源于stack exchange,提问作者Dudus
相关产品推荐
相关产品推荐

