Java 快速编辑私有变量

Java 快速编辑私有变量,java,reflection,Java,Reflection,在我的项目中,我希望快速读取私有ish变量并对其进行修改。我最初打算进行反思,但我的想法是这样做效率太低 //Reference for what I need to get data from. public class SomeControllerInALibraryThatICantEdit { //I can easily get an instance of the controller public static final SomeControllerInLarg

在我的项目中,我希望快速读取私有ish变量并对其进行修改。我最初打算进行反思,但我的想法是这样做效率太低

//Reference for what I need to get data from.
public class SomeControllerInALibraryThatICantEdit {

    //I can easily get an instance of the controller
    public static final SomeControllerInLargeLibrary instance;

    //I need to read from and make changes to the data object quickly.
    //It is final, so I don't need to worry about this object changing or being reset.
    private final Subclass dataClass = new Subclass();

    private class Subclass {

        //I can get a pointer to this once then treat it like any other array.
        public float[] arr;


        //This is the problematic part. I need to be able to quickly check changes and 
        //set this every update. Keeping in mind there are multiple dataPoints.
        public short dataPoint;

    }

}
获取和设置数据点的快速有效方法是什么?我可以使用反射,但我希望有更好的方法来解决这个问题。我能否以某种方式创建一个表示子类并将它们的指针链接在一起的Pojo

如果我只是用叉子叉图书馆,让它在我所做的工作中更好地工作,那么这就违背了我项目的目的

但我知道使用反射是非常缓慢的

事实并非如此

为该变量创建私有静态final MethodHandle,它将被优化到与使用普通代码几乎相同的性能-可以肯定的是,调用它的次数将比调用它的次数少很多,因此您也可以每秒调用它200次,而不是2000次。
仅创建反射访问器非常慢,但您只需要执行一次

private static final MethodHandle dataGetter;

static {
    Field dataField;
    try {
        dataField = SomeControllerInALibraryThatICantEdit.class.getDeclaredField("dataClass");
        dataField.setAccessible(true); // or trySetAccessible for new java
        dataGetter = MethodHandles.lookup().unreflectGetter(dataField);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}
并使用类似于:

DataClass data = (DataClass) dataGetter.invokeExact(SomeControllerInALibraryThatICantEdit.instance);
注意,即使invokeExact方法需要签名中的对象,也必须提供有效类型的变量,因为它使用
@PolymorphicSignature

您还可以使用:

dataGetter = MethodHandles.lookup().unreflectGetter(dataField).bindTo(SomeControllerInALibraryThatICantEdit.instance); 
然后,您可以跳过实例,它可能也会快一点

这里唯一慢的部分是MethodHandle的创建。
但性能也可能依赖于JVM,就像我认为在android虚拟机上,JVM的速度通常较慢一样

但在hotspot上,速度应该非常快,以下是我以前的基准测试结果:

Benchmark                                                      Mode  Cnt  Score   Error  Units
normalDirectAccess                                             avgt   10  2,867 ± 0,142  ns/op
somethingPrivateFieldAccessor_static_final_handle_access       avgt   10  2,827 ± 0,058  ns/op
somethingPrivateFieldAccessor_static_final_handle_bound_access avgt   10  2,859 ± 0,084  ns/op
完整的基准可以在这里找到:像其他类型的反射等,但这一小部分应该足以回答这个问题


此外,由于此字段是最终字段,且在单例中。。。您可能只需获取一次,然后重复使用

您的问题没有意义什么部分?我希望能够读取和设置数据点,但我想尝试找到一种比每次需要时使用反射更快的方法(大约每秒200次)。你没有解释为什么首先需要使用反射为什么不能简单地使用getter/setter?你能详细解释一下为什么你认为反思在这里是必要的吗?当你说“快”的时候,你在问什么?如果你还不能获得或设置它,你怎么知道你选择的任何方式都不够快?