来自 Java 反射的字段 class 可以作用于任何对象吗?

Can a Field class from Java reflection work on any object?

我很好奇是否可以存储 Field 对象的实例并将其用于我传递给它的任何对象。我正在做大量的反思工作,我记得在某处读到存储 Field 对象并将其用作单例(或多或少)以从 class.[= 快速访问该字段是不安全的14=]

这真的可能吗,或者我正在尝试做的事情是危险的还是有任何缺陷的?我做了一个快速测试来检查,它似乎有效......但我不确定这个测试是否真的证明了这一点。

这假设我们被允许访问该字段并且不会引发 SecurityException。


用于测试的代码:

package test;

import java.lang.reflect.Field;

public class TestClass {

    public static void main(String[] args) {
        Field fa = null;
        Field fb = null;

        for (Field f : Test.class.getDeclaredFields()) {
            switch (f.getName()) {
            case "a":
                fa = f;
                break;
            case "b":
                fb = f;
                break;
            }
        }

        fa.setAccessible(true);
        fb.setAccessible(true);

        Test ta = new Test(5, "test");      
        Test tb = new Test(54, "new string");

        try {
            System.out.println(fa.get(ta) + " " + fa.get(tb) + " " + fb.get(ta) + " " + fb.get(tb));
        } catch (IllegalArgumentException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

@SuppressWarnings("unused")
class Test {

    private int a;
    private String b;

    public Test(int a, String b) {
        this.a = a;
        this.b = b;
    }
}

产量:

5 54 test new string

这非常好,它应该以这种方式工作。 Field 指的是特定 class 中的字段,而不是 class 的特定实例(对象) - 因此您可以将其与class.

的任何实例

当然,如果Field引用classTest中的字段,那么你只能在Test类型的对象上使用它。如果您尝试在 Field 上调用 get(Object o) 传递给它的东西不是 Test 对象,您将得到一个 IllegalArgumentException

请参阅 Field.get(Object o) 的 API 文档。

通过反射,您几乎可以做任何事情,还可以设置私有变量或从对象外部调用私有方法。 在运行时,这不会被检查。据我所知,它只是编译器的关键字(我在这方面可能有误,请纠正我)。