来自 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 文档。
通过反射,您几乎可以做任何事情,还可以设置私有变量或从对象外部调用私有方法。
在运行时,这不会被检查。据我所知,它只是编译器的关键字(我在这方面可能有误,请纠正我)。
我很好奇是否可以存储 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 文档。
通过反射,您几乎可以做任何事情,还可以设置私有变量或从对象外部调用私有方法。 在运行时,这不会被检查。据我所知,它只是编译器的关键字(我在这方面可能有误,请纠正我)。