Java 反射是可访问的方法

2022-09-04 01:58:23

我正在学习反思。当我执行以下代码时:

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;

}

结果为假。但这不是真的,因为我可以以这种方式访问:?protectedBufferfirstBase.protectedBuffer


答案 1

这是因为您没有测试字段是否可访问protectedBufferfirstBaseField.isAccessible();

这里发生的事情是,您检查哪个值是 Field 的基类。此标志不会告诉您字段是否可以由java访问修饰符访问,它会告诉您这些修饰符当前是否被忽略。AccessibleObject

当你得到假时,它只是意味着java访问规则仍然存在,并且没有被反射机制覆盖。firstBaseField.isAccessible()

setAccessible()

将此对象的可访问标志设置为指示的布尔值。值 true 表示反射的对象在使用时应禁止 Java 语言访问检查。值 false 表示反射的对象应强制执行 Java 语言访问检查。

编辑

要测试该字段是否可以通过 java 访问修饰符访问,您可以尝试访问它并捕获 ,如下面的示例波纹管所示。IllegalAccessException

Field field = instance.getClass().getDeclaredField("someField");
//  IllegalAccessException
field.get(instance);

答案 2

您错误地理解了此可访问标志。根据文档,当可访问为 true 时,将绕过所有访问检查(您可以使用此字段或方法,Java 不会检查它是否公开)。当可访问为 false 时,访问检查将起作用。由于它是在文档中编写的,因此默认情况下,它适用于任何(甚至对于字段或方法)。falseAccessibleObjectpublic