Java Reflection:从属性中检索值的快速​​方法

时间:2018-01-18 10:14:23

标签: java reflection

我想用最快的方法从属性中检索值。

我应该使用:

public Object getValue(Object obj, Field field) {
    field.setAccessible(true);
    return field.get(obj);
}

或者我应该使用:

public Object getValue(Object obj, Field field) throws Exception {
    StringBuilder methodName = new StringBuilder();
    methodName.append("get");
    methodName.append(field.getName().substring(0, 1).toUpperCase());
    methodName.append(field.getName().substring(1, field.getName().length()));
    for (Method method : methods) {
        if (method.getName().equals(methodName.toString())) {
            return method.invoke(obj);
        }
    }
}

或者我应该使用:

public Object getValue(Object obj, Field field) throws Throwable {
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        StringBuilder methodName = new StringBuilder();
        methodName.append("get");
        methodName.append(field.getName().substring(0, 1).toUpperCase());
        methodName.append(field.getName().substring(1, field.getName().length()));
        for (Method method : methods) {
            if (method.getName().equals(methodName.toString())) {
                MethodHandle mh = lookup.findVirtual(obj.getClass(), methodName.toString(), MethodType.methodType(field.getType()));

                return mh.invoke(obj);
            }
        }
    }

提前致谢。

2 个答案:

答案 0 :(得分:2)

有不同的级别:

  • 字段访问是字段访问。访问该字段的方法也将...访问该字段。只是有更多的开销。
  • 您必须随着时间的推移维护您的代码。

第一点表明“直接”字段访问应该总是更快(特别是考虑到这种方法非常短 - 并且JIT在内联方法方面要好得多)。引出第二点:简单地问问自己这三种方法中哪一种最容易阅读和理解。

关键是反射调用很昂贵。 方法句柄概念旨在提高该成本(通过避免检查使用反射的方法调用正在每个时间)。因此,如果您真的对找到“最佳”代码感兴趣,那么答案可能围绕一个计算方法句柄一次的解决方案,然后重新使用用于后续通话。实例化一个方法句柄只是为了进行一次调用是绝对没有意义的。没有什么可以从中获得 - 只有当你反复使用方法句柄来进行调用时,方法句柄比普通的反射更“便宜”。

当然,真正的答案是:你退一步,学习如何正确benchmark java代码,然后在你的中做一些测量 context,environment - 您的数据,代码。然后得出你的最终结论。我也同意spi给出的评论 - 如果表现对您至关重要,那么反射(或多或少)是不去

答案 1 :(得分:1)

如果您使用的是Java 8,那么

  1. 如果你想使用run reflection那么你应该考虑LambdaMetaFactory,它提供与直接方法调用大致相同的性能 [faster-alternatives-to-javas-reflection]

  2. 如果要使代码可配置,但配置在运行时不会更改。然后应该使用AnnotationProcessor处理器来生成代码。它将配置,性能,维护和完美结合在一起。易于使用。

  3. [annotation processing] [annotation Processing with maven]