Poison

AccessibleObject.isAccessible()

关于反射时经常使用的 AccessibleObject.isAccessible() 方法,笔者一直以为是被 public 修饰就返回 true,其他的就返回 false,今天调试代码时发现对 ArrayList 的无参构造函数调用 isAccessible() 返回的竟然是 false,于是查阅了相关代码,在 java.lang.reflect.AccessibleObject 类中有以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* Get the value of the {@code accessible} flag for this object.
*
* @return the value of the object's {@code accessible} flag
*/
public boolean isAccessible() {
return override;
}

// Indicates whether language-level access checks are overridden
// by this object. Initializes to "false". This field is used by
// Field, Method, and Constructor.
//
// NOTE: for security purposes, this field must not be visible
// outside this package.
boolean override;

根据源码可知,isAccessible() 返回的为字段 override 的值,注释表示该字段表明是否语言级别的检查被覆盖,默认为 false,并不是笔者之前认为的修饰符是否为 public 的含义,个人认为这个方法名具有迷惑性,因为在 Oracle 的官方文档 Controlling Access to Members of a Class 中,将修饰符称为 Access level modifiers,容易让人误解 AccessibleObject.isAccessible() 的含义。

最后附上测试代码,输出结果为 false:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package me.tianshuang;

import java.lang.reflect.Constructor;
import java.util.ArrayList;

public class AccessibleTest {

public static void main(String[] args) throws NoSuchMethodException {
Class<?> clazz = ArrayList.class;
Constructor<?> constructor = clazz.getDeclaredConstructor();
System.out.println(constructor.isAccessible());
}

}
References

java - Why a public constructor is not accessible via reflection - Stack Overflow