我正在学习反思。当我执行以下代码时:
package main;
import java.lang.reflect.Field;
public class Main {
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
Base firstBase = new Base();
Field firstBaseField = firstBase.getClass().getDeclaredField("protectedBuffer");
System.out.println(firstBaseField.isAccessible());
}
}
这是基本类:
package main;
public class Base {
private StringBuffer buffer;
protected StringBuffer protectedBuffer;
public StringBuffer buffer2;
}
结果是错误的。但这不是真的吗,因为我可以用这种方式访问protectedBuffer
:firstBase.protectedBuffer
?
这是因为在执行firstBaseField.isAccessible();
时没有测试字段protectedBuffer
是否可访问
这里发生的是检查AccessibleObject
的值,它是Field的基类。这个标志不会告诉您字段是否可以被java访问修饰符访问,而是告诉您这些修饰符当前是否被忽略。
当您在firstBaseField.isAccessible()
上得到false时,这仅仅意味着java访问规则仍然存在,并且不会被反射机制覆盖。
setAccessible((
将此对象的可访问标志设置为指示的布尔值。值true表示反射对象在使用时应禁止Java语言访问检查。值false表示反射的对象应该强制执行Java语言访问检查。
编辑
要测试java访问修饰符是否可以访问该字段,可以尝试访问它并捕获IllegalAccessException
,如下面的示例所示。
Field field = instance.getClass().getDeclaredField("someField");
// IllegalAccessException
field.get(instance);
您错误地理解了这个可访问的标志。根据文档,当accessible为true时,将绕过所有访问检查(您可以使用此字段或方法,Java不会检查它是否为公共(。如果accessible为false,则访问检查有效。正如文档中所写的,对于任何AccessibleObject
(甚至对于public
字段或方法(,默认情况下都是false
。
从Java 9开始,isAccessible
方法已被弃用。您可以改用canAccess
。
默认情况下,使用Class#getDeclaredField(String name)
检索的所有Fields
都将accessible
标志设置为false。对于public
字段buffer2
,也会得到false。
Field
类是AccessibleObject
:的一个子类
默认情况下,反射对象不可访问。