以下用例是否被认为有理由进行反射(reflection)?
有一堆从 XSD 生成的类(目前项目中有数百个)代表各种响应。
所有这些响应都包含通用响应数据结构,而不是对其进行扩展。
当超时等事件发生时,我只需要将单个字符串设置为特定值。
如果这些类扩展了公共(public)响应结构,我总是可以设置此响应代码而无需反射,但事实并非如此。
因此我为我的服务编写了简单的实用程序,它使用反射来获取 String 字段的 setter 方法并使用预定义的值调用它。 我唯一知道的替代方法是使用特定于类的方法,这些方法会复制代码来处理超时,唯一的区别是返回的 Response 类。
protected T handleTimeout(Class<T> timeoutClass) {
try {
T timeout = timeoutClass.newInstance();
Method setCode = timeoutClass.getDeclaredMethod(SET_RESPONSE_CODE, String.class);
setCode.invoke(timeout, Response.TIMEOUT.getCode());
return timeout;
} catch (InstantiationException | IllegalAccessException | SecurityException | NoSuchMethodException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
throw new RuntimeException("Response classes must have field: \"code\" !");
}
}
相关事实:
- 此 setter 方法永远不应更改,因为它需要重新编写数百个接口(interface)
有人可以指出我是否遗漏了一些陷阱,或者是否有替代的反射解决方案可以达到相同的结果?
编辑:我无权对 XSD 进行任何更改,因此任何解决方案都必须在本地完成。序列化此类对象应该没有问题,因为它们在组件之间共享。
最佳答案
首先,@kutschkem 建议有一个标准的、正常的日常解决方案,特别是:声明一个只包含这个 setter 方法的接口(interface),并在每个需要它的类中实现该接口(interface)。这使用标准多态性来完全满足您的需求。
我知道这需要更改很多类的定义(但更改是微不足道的 - 只需将“implements MytimeoutThing”添加到每个类) - 即使对于 1000 个类,这对我来说似乎也是一个相当容易的修复。
我认为反射确实存在问题:
您正在为所有必须支持的类创建一个 secret 接口(interface),但该接口(interface)没有契约(Contract) - 当新开发人员想要添加一个新类时,他必须神奇地知道名称和签名这个方法——如果他弄错了,代码就会在运行时失败,因为编译器不知道这个契约。 (因此,像拼错 setter 名称这样简单的事情不会被编译器识别)
它很丑陋,隐藏起来并且不属于软件的任何特定部分。维护这些类中的任何一个的开发人员会发现这个函数(setter)注意到它永远不会被调用并且只是删除它 - 毕竟项目其余部分中没有代码引用该 setter 所以它显然不需要。
很多静态分析工具都无法工作 - 例如,在大多数 IDE 中,您可以建立调用特定函数的所有位置以及调用特定函数的所有位置 - 显然是这种功能如果您使用反射则不可用。在一个有数百个几乎相同类的项目中,我不想失去这个设施。
关于java - 在此用例中使用反射来解决我不允许修复的设计问题是否合理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30595218/