Module java.base

Class AccessibleObject

java.lang.Object
java.lang.reflect.AccessibleObject
所有已实现的接口:
AnnotatedElement
直接已知的子类:
Executable, Field

public class AccessibleObject extends Object implements AnnotatedElement
AccessibleObject类是FieldMethodConstructor对象(称为反射对象)的基类。它提供了将反射对象标记为在使用时抑制Java语言访问控制检查的能力。这允许具有足够特权的复杂应用程序,如Java对象序列化或其他持久性机制,以一种通常被禁止的方式操作对象。

Java语言访问控制阻止在其顶级类之外使用私有成员;在其包之外使用包访问成员;在其包或子类之外使用受保护成员;以及在其模块之外使用公共成员,除非它们在一个导出包中声明,并且用户读取它们的模块。默认情况下,当使用FieldMethodConstructor来获取或设置字段,调用方法,或创建和初始化类的新实例时,Java语言访问控制是强制执行的(有一个变化)。每个反射对象都会检查使用它的代码是否在适当的类、包或模块中。当由没有Java类的堆栈的JNI代码调用时,只有当成员和声明类是公共的,并且类在一个对所有模块都导出的包中时,检查才会成功。

与Java语言访问控制的一个变化是,反射对象的检查假定可读性。也就是说,包含反射对象使用的模块被假定读取包含底层字段、方法或构造函数的模块。

Java语言访问控制的检查是否可以被抑制(因此,访问是否可以被启用)取决于反射对象是否对应于导出或开放包中的成员(参见setAccessible(boolean))。

参见Java语言规范:
6.6 访问控制
自版本:
1.2
外部规范
  • Constructor Details

    • AccessibleObject

      @Deprecated(since="17") protected AccessibleObject()
      Deprecated.
      构造函数:仅由Java虚拟机使用。
  • Method Details

    • setAccessible

      public static void setAccessible(AccessibleObject[] array, boolean flag)
      通过单个安全检查(为了效率)设置一组反射对象的accessible标志。

      当每个反射对象的访问可以按照setAccessible(boolean)指定的方式启用时,可以使用此方法来启用数组中所有反射对象的访问。

      如果存在安全管理器,则首先使用ReflectPermission("suppressAccessChecks")权限调用其checkPermission方法。

      如果输入array的元素之一是类java.lang.ClassConstructor对象且flag为true,则还会抛出SecurityException

      参数:
      array - AccessibleObjects数组
      flag - 每个对象中accessible标志的新值
      抛出:
      InaccessibleObjectException - 如果无法为数组中的所有对象启用访问
      SecurityException - 如果安全管理器拒绝请求或数组中的元素是java.lang.ClassConstructor对象
      参见:
    • setAccessible

      public void setAccessible(boolean flag)
      将此反射对象的accessible标志设置为指定的布尔值。值为true表示在使用时反射对象应抑制Java语言访问控制检查。值为false表示在使用时反射对象应强制执行Java语言访问控制检查,其中类描述中有所述的变化。

      如果调用者在类C中使用此方法来启用声明类 D成员访问,则以下情况之一成立:

      • CD在同一模块中。
      • 成员是public的,D在将其包含的模块导出到至少包含C的模块时是public的。
      • 成员是protected static的,D在将其包含的模块导出到至少包含C的模块时是public的,并且CD的子类。
      • D在将其包含的模块开放到至少包含C的模块中。未命名和开放模块中的所有包都对所有模块开放,因此当D在未命名或开放模块中时,此方法总是成功的。

      如果没有调用者类的堆栈上的JNI代码,则此方法可用于启用声明类 D成员访问,当且仅当:

      • 成员是public的,D在将其包含的模块无条件导出

      当声明类与调用者位于不同模块且包含声明类的包未对调用者的模块开放时,此方法无法用于启用对私有成员、具有默认(包)访问权限的成员、受保护实例成员或受保护构造函数的访问。

      此方法无法用于启用对不可修改的最终字段的写入访问。以下字段是不可修改的:

      • 在任何类或接口中声明的静态最终字段
      • 隐藏类中声明的最终字段
      • 记录中声明的最终字段

      accessible标志为true时,仅抑制Java语言访问控制检查以仅启用对这些不可修改最终字段的读取访问。

      如果存在安全管理器,则首先使用ReflectPermission("suppressAccessChecks")权限调用其checkPermission方法。

      参数:
      flag - accessible标志的新值
      抛出:
      InaccessibleObjectException - 如果无法启用访问
      SecurityException - 如果安全管理器拒绝请求
      外部规范
      参见:
    • trySetAccessible

      public final boolean trySetAccessible()
      设置此反射对象的accessible标志为true(如果可能)。此方法设置accessible标志,就好像调用setAccessible(true)一样,并返回accessible标志的可能更新值。如果无法启用访问权限,即无法抑制检查或Java语言访问控制,则此方法返回false(与 setAccessible(true)在失败时抛出InaccessibleObjectException不同)。

      如果此反射对象的accessible标志为true,则此方法不执行任何操作。

      例如,调用者可以在私有实例方法p.T::privateMethodMethod对象上调用trySetAccessible,以在调用Method时抑制Java语言访问控制的检查。如果p.T类与调用者的模块不同,并且包p对至少调用者的模块开放,则下面的代码成功将accessible标志设置为true

       
          p.T obj = ....;  // p.T的实例
          :
          Method m = p.T.class.getDeclaredMethod("privateMethod");
          if (m.trySetAccessible()) {
              m.invoke(obj);
          } else {
              // 包p未对调用者开放以访问T的私有成员
              ...
          }
      

      如果此方法由没有调用者类的JNI代码调用,则只有在成员和声明类为public,并且类在无条件导出的包中时,才能设置accessible标志。

      如果存在安全管理器,则首先调用其checkPermission方法,其中包含ReflectPermission("suppressAccessChecks")权限。

      返回:
      如果accessible标志设置为true,则返回true;如果无法启用访问权限,则返回false
      抛出:
      SecurityException - 如果安全管理器拒绝请求
      自版本:
      9
      外部规范
      另请参见:
    • isAccessible

      @Deprecated(since="9") public boolean isAccessible()
      Deprecated.
      This method is deprecated because its name hints that it checks if the reflected object is accessible when it actually indicates if the checks for Java language access control are suppressed. This method may return false on a reflected object that is accessible to the caller. To test if this reflected object is accessible, it should use canAccess(Object).
      获取此反射对象的accessible标志的值。
      返回:
      对象的accessible标志的值
    • canAccess

      public final boolean canAccess(Object obj)
      测试调用者是否可以访问此反射对象。如果此反射对象对应于实例方法或字段,则此方法测试调用者是否可以访问具有反射对象的给定obj。对于实例方法或字段,obj参数必须是declaring class的实例。
      对于静态成员和构造函数,则obj必须为null

      如果accessible标志设置为true,即Java语言访问控制的检查被抑制,或者如果调用者可以按照Java语言规范中指定的方式访问成员,那么此方法返回true,并在类描述中指定的变化。如果此方法由没有调用者类的JNI代码调用,则如果成员和声明类为public,并且类在无条件导出的包中,则此方法返回true

      参数:
      obj - 如果它是实例方法或字段的声明类的实例对象
      返回:
      如果调用者可以访问此反射对象,则返回true
      抛出:
      IllegalArgumentException -
      • 如果此反射对象是静态成员或构造函数,并且给定的obj为非null,或
      • 如果此反射对象是实例方法或字段,并且给定的objnull或不是成员的declaring class的子类。
      请参阅Java语言规范
      6.6 访问控制
      自版本:
      9
      外部规范
      另请参见:
    • getAnnotation

      public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
      如果指定类型的注释存在,则返回此元素的该类型注释,否则返回null。

      请注意,此方法返回的任何注释都是声明注释。

      指定者:
      getAnnotation 在接口 AnnotatedElement
      实现要求:
      默认实现会抛出UnsupportedOperationException;子类应该重写此方法。
      类型参数:
      T - 要查询并返回的注释类型
      参数:
      annotationClass - 与注释类型对应的Class对象
      返回:
      如果此元素上存在指定注释类型的注释,则返回该元素的该注释,否则返回null
      抛出:
      NullPointerException - 如果给定的注释类为null
      自版本:
      1.5
    • isAnnotationPresent

      public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
      如果指定类型的注释存在于此元素上,则返回true,否则返回false。此方法主要设计用于方便访问标记注释。

      此方法返回的真值等同于:getAnnotation(annotationClass) != null

      指定者:
      isAnnotationPresent 在接口 AnnotatedElement
      参数:
      annotationClass - 与注释类型对应的Class对象
      返回:
      如果此元素上存在指定注释类型的注释,则返回true,否则返回false
      抛出:
      NullPointerException - 如果给定的注释类为null
      自版本:
      1.5
    • getAnnotationsByType

      public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)
      返回与此元素关联的注释。如果此元素没有与之关联的注释,则返回值是长度为0的数组。此方法与AnnotatedElement.getAnnotation(Class)之间的区别在于,此方法会检测其参数是否为可重复注释类型(JLS 9.6),如果是,则尝试通过“查看”容器注释来查找一个或多个该类型的注释。调用此方法的调用者可以修改返回的数组;这不会影响返回给其他调用者的数组。

      请注意,此方法返回的任何注释都是声明注释。

      指定者:
      getAnnotationsByType 在接口 AnnotatedElement
      实现要求:
      默认实现会抛出UnsupportedOperationException;子类应该重写此方法。
      类型参数:
      T - 要查询并返回的注释类型
      参数:
      annotationClass - 与注释类型对应的Class对象
      返回:
      如果与此元素关联的注释是指定注释类型的,则返回所有此元素的该注释,否则返回长度为零的数组
      抛出:
      NullPointerException - 如果给定的注释类为null
      自版本:
      1.8
    • getAnnotations

      public Annotation[] getAnnotations()
      返回存在于此元素上的注释。如果此元素上没有注释存在,则返回值是长度为0的数组。调用此方法的调用者可以修改返回的数组;这不会影响返回给其他调用者的数组。

      请注意,此方法返回的任何注释都是声明注释。

      指定者:
      getAnnotations 在接口 AnnotatedElement
      返回:
      此元素上存在的注释
      自版本:
      1.5
    • getDeclaredAnnotation

      public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass)
      如果直接存在指定类型的注释,则返回此元素的该类型注释,否则返回null。此方法会忽略继承的注释。(如果此元素上没有直接存在的注释,则返回null。)

      请注意,此方法返回的任何注释都是声明注释。

      指定由:
      getDeclaredAnnotation 在接口 AnnotatedElement
      类型参数:
      T - 要查询并返回的注解类型
      参数:
      annotationClass - 对应于注解类型的Class对象
      返回:
      如果直接存在于此元素上的指定注解类型的注解,否则为null
      抛出:
      NullPointerException - 如果给定的注解类为null
      自版本:
      1.8
    • getDeclaredAnnotationsByType

      public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass)
      如果此元素的指定类型的注解是直接存在间接存在,则返回此元素的注解。此方法忽略继承的注解。如果在此元素上既没有直接也没有间接存在指定的注解,则返回值为长度为0的数组。此方法与AnnotatedElement.getDeclaredAnnotation(Class)之间的区别在于,此方法检测其参数是否为可重复注解类型(JLS 9.6),如果是,则尝试通过“查找”容器注解来找到一个或多个该类型的注解。调用此方法的调用者可以修改返回的数组;这不会影响返回给其他调用者的数组。

      请注意,此方法返回的任何注解都是声明注解。

      指定由:
      getDeclaredAnnotationsByType 在接口 AnnotatedElement
      类型参数:
      T - 要查询并返回的注解类型
      参数:
      annotationClass - 对应于注解类型的Class对象
      返回:
      如果直接或间接存在于此元素上的指定注解类型的所有注解,否则为长度为零的数组
      抛出:
      NullPointerException - 如果给定的注解类为null
      自版本:
      1.8
    • getDeclaredAnnotations

      public Annotation[] getDeclaredAnnotations()
      返回直接存在于此元素上的注解。此方法忽略继承的注解。如果在此元素上没有直接存在的注解,则返回值为长度为0的数组。调用此方法的调用者可以修改返回的数组;这不会影响返回给其他调用者的数组。

      请注意,此方法返回的任何注解都是声明注解。

      指定由:
      getDeclaredAnnotations 在接口 AnnotatedElement
      实现要求:
      默认实现会抛出UnsupportedOperationException;子类应该重写此方法。
      返回:
      直接存在于此元素上的注解
      自版本:
      1.5