当我使用内省时,我有以纯文本编写的类,方法和属性名称 . 就像在这个简短的演示:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class SO {
public static void main(String[] args)
throws NoSuchMethodException, ClassNotFoundException,
InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchFieldException {
final Class<?> myClass = Class.forName("myClass");
final Constructor<?> defaultConstructor = myClass.getDeclaredConstructor();
final Object myInstance = defaultConstructor.newInstance();
final Method myMethod = myClass.getDeclaredMethod("myMethod");
myMethod.invoke(myInstance, "arg1", 3, true);
final Field myFied = myClass.getDeclaredField("myFied");
final Object value = myFied.get(myInstance);
}
}
由于没有对此代码进行编译检查,如果我的目标类/方法/字段/签名在代码库中发生了任何变化,它可能会在运行时中断 . 有时IDE可以在重构时提供帮助,但通常我们可能会错过更改并在运行时出现致命错误 .
你知道避免这种问题的方法吗?
注意:没有有用答案的任何'Avoid reflection whenever possible'都会得到-1 .
这不是一个威胁:我的问题不是'should I use introspection ?'而且我觉得答案纯粹是在污染这个问题 .
7 回答
编写自动化集成测试,使用 生产环境 中使用的实际配置文件并测试系统的完整路径 . 设置持续集成,以便在这些集成测试失败时立即通知您 .
由于这些类型的错误只会在运行时出现,因此自动化测试是在受控环境中模拟运行时行为的方法 .
是 . 不要那么多使用反射/内省 . 非反射代码本质上不如其反射等效代码脆弱,并且更容易阅读并且显着更快 .
我不知道任何IDE支持检查反射代码是否存在可能的运行时错误 . 事实上,在一般情况下,这是不可能的,因为它等同于停机问题 .
要说清楚,我没有说你根本不应该使用反射 . 存在反射是最佳解决方案的问题 . 但是,如果您发现基于反射的代码的脆弱性是一个重要问题,那么您可能使用它太多了 .
我会尝试重构任何使用硬编码反射的代码来删除硬编码 . 例如,你可以重构:
如:
这个例子显然是微不足道的,但重点是尝试使用变量来确定该类而不是硬编码 .
更好的是,您可以对其进行注释,然后使用反射来获取带注释的元素,而不是对类,方法或字段名称进行硬编码 .
根据其他答案,尽可能避免反思 .
但有时你不能(例如Spring MVC bean绑定,Wicket PropertyModels等) . 在这些情况下以及使用反射来记录(在get / set方法中)这些方法,我倾向于添加静态字符串,例如对于一个名为surname属性的bean
并在代码中使用
PROPERTY_SURNAME
而不是"surname"
本身 . 它是开发人员改变get / set方法的暗示 .当然 . 尽可能避免反射 . 由于反射的意图是围绕类型检查,因此在编译时没有其他可靠的方法来检查类型 . 如果您找到了针对特定案例的方法,则可以避免在这种情况下进行反思 .
你的例子很小,可以提供很多提示,但有时我会做一件事:
编写一个Java接口,其中包含要调用的方法 . 使用该接口获取此接口的方法对象 . 然后使用它的名称和参数来查找您真正想要调用的方法 . 例如 . 每个接口一个方法,因此类名表示您想要的操作 .
你的myClass不需要实现接口......
我会说“尝试使用Jython”,而不是说“不要使用反射” .
http://onjava.com/pub/a/onjava/2002/03/27/jython.html?page=2
请注意,那篇文章此时已相当陈旧;我只提供了它作为一个例子 . 例如,"Python coders rarely use simple get and set methods, preferring to access the variable directly."部分完全忽略了Python的
property()
builtin(当时相当新的)的实用性,它允许透明的getter和setter使用,提供两全其美 . 但是,这种情况越来越严重,所以无论如何 .哦,对,你可能要看一个模块是http://www.jython.org/docs/library/inspect.html