Java中的类型安全方法反射

jth*_*thg 6 java compiler-construction reflection

是否有任何实用的方法以类型安全的方式引用类的方法?一个基本的例子是,如果我想创建类似以下实用程序函数:

public Result validateField(Object data, String fieldName, 
                            ValidationOptions options) { ... }
Run Code Online (Sandbox Code Playgroud)

为了打电话,我必须这样做:

validateField(data, "phoneNumber", options);
Run Code Online (Sandbox Code Playgroud)

这迫使我要么使用魔法字符串,要么使用该字符串声明一个常量.

我很确定没有办法用库存Java语言来解决这个问题,但是有某种(生产级)预编译器或替代编译器可以提供解决方法吗?(类似于AspectJ如何扩展Java语言)做以下事情会很好:

public Result validateField(Object data, Method method, 
                            ValidationOptions options) { ... }
Run Code Online (Sandbox Code Playgroud)

并称之为:

validateField(data, Person.phoneNumber.getter, options);
Run Code Online (Sandbox Code Playgroud)

PSp*_*eed 6

正如其他人提到的,没有真正的方法可以做到这一点……而且我还没有看到支持它的预编译器。至少可以说,语法会很有趣。即使在您的示例中,它也只能涵盖用户可能想要做的潜在反射可能性的一小部分,因为它不会处理带参数的非标准访问器或方法等。

即使在编译时无法检查,如果您希望错误代码尽快失败,那么一种方法是在类初始化时解析引用的 Method 对象。

想象一下,您有一个实用方法来查找可能会引发错误或运行时异常的 Method 对象:

public static Method lookupMethod( Class c, String name, Class... args ) {
    // do the lookup or throw an unchecked exception of some kind with a really
    // good error message
}
Run Code Online (Sandbox Code Playgroud)

然后在您的类中,使用常量来预先解析您将使用的方法:

public class MyClass {
    private static final Method GET_PHONE_NUM = MyUtils.lookupMethod( PhoneNumber.class, "getPhoneNumber" );

    ....

    public void someMethod() {
        validateField(data, GET_PHONE_NUM, options);
    }
}
Run Code Online (Sandbox Code Playgroud)

至少,一旦第一次加载 MyClass,它就会失败。

我经常使用反射,尤其是 bean 属性反射,而且我刚刚习惯了运行时的后期异常。但是这种风格的 bean 代码由于各种其他原因往往会出错,而且非常动态。对于介于两者之间的事情,上述内容会有所帮助。