Java 反射包下常用类介绍(Member、Field、AnnotatedElement、Type、Method 等等)

修订信息

  1. 2021.6.4 修复全局;替换带来的问题

Type

Type 是 Java 编程语言中所有类型的公共超接口。这些类型包括原始类型(raw type)、参数化类型(parameterized type)、数组类型(array type)、类型变量(type variable )和原生类型(primitive type)。

派生类或接口说明
java.lang.ClassJava 类 API,如 java.lang.String
java.lang.reflect.GenericArrayType泛型数组类型
java.lang.reflect.ParameterizedType泛型参数类型
java.lang.reflect.TypeVariable泛型类型变量,如 Collection<E&gt; 中的 E
java.lang.reflect.WildcardType泛型通配类型
方法说明
getTypeName()返回描述此类型的字符串,包括有关任何类型参数的信息

TypeVariable

TypeVariable 是类型变量的通用超接口。类型变量是在反射方法第一次需要它时创建的,如此包中所指定的。如果一个类型变量引用类型 T (即类、接口或注释类型),并且 T 通过第 n 封闭类(见 JLS 8.1.2)声明,然后创建 T 需要的解析度(参见 JVMS 5) 第 i 的封闭类,从 i = 0 到 n、包容。创建类型变量时不能导致其边界的创建。重复创建类型变量没有任何效果。
可以在运行时实例化多个对象来表示给定的类型变量。即使类型变量只创建一次,这并不意味着需要缓存表示该类型变量的实例。但是,代表类型变量的所有实例必须彼此 equal()。因此,类型变量的用户不能依赖实现此接口的类实例的标识。

方法说明
getBounds()返回一个表示此类型变量的上界的 Type 对象数组。注意,如果没有显式声明上界,上界就是 Object
getGenericDeclaration()返回表示声明此类型变量的泛型声明的 GenericDeclaration 对象
getName()返回此类型变量的名称
getAnnotatedBounds()返回一个 AnnotatedType 对象数组,该数组表示使用类型来表示由此 TypeVariable 表示的类型参数的上界。数组中对象的顺序对应于类型形参声明中边界的顺序。如果类型参数声明没有边界,则返回长度为 0 的数组

JLS(Java 语言规范) 4.4

类型变量是在类、接口、方法和构造器中用作类型的非限定标识符
类型变量可以声明为泛型类声明、泛型接口声明、泛型方法声明和泛型构造器声明中的类型参数

TypeParamerter:
{TypeParameterModifier} Identifier [TypeBound]

TypeParameterModifier:
Annotation

TypeBound:
extends TypeVariable
extends ClassOrInterfaceType {AdditionalBound}

AdditionalBound:
& InterfaceType

每个声明为类型参数的类型变量都有一个边界。如果对某个类型变量没有声明任何边界,则默认其边界为 Object。如果声明了边界,则它有下列两种情况构成:

  • 单个类型变量 T
  • 类或接口类型 T,后面可能还有接口类型 I1 &……&In

如果 I1… In 类型中任何一个是类类型或类型变量,那么就会产生一个编译时错误。
对于边界来说,其所有构成类型的擦除必须都是互不相同的,否则就会产生一个编译时错误。
如果两个接口类型是同一个泛型接口的不同参数化版本,那么类型变量就不能同时是这两个接口类型的子类型,否则就会产生一个编译时错误。
类型在边界中的顺序只在两种情况下才显得重要,第一种是类型变量的擦除取决于边界中的第一个类型;第二种是类类型或类型变量只能出现在第一个类型的位置。
边界为 T& I1 &……&In 的类型变量 x 的成员,是由位于类型变量声明处的交集类型 T& I1 &……&In 的成员构成的。

public class C {
    public void mCPublic() {
    }

    protected void mCProtected() {
    }

    void mcPackage() {
    }

    private void mCPrivate() {
    }
    
    
    
    interface I{
        void mI()}
    
    class CT extends C implements I{
        @Override
        public void mI() {
            
        }
    }
    
    class Text{

        <T extends C & I> void test(T t) {
            t.mI()// OK
            t.mCPublic()// OK
            t.mCProtected()// OK
            t.mcPackage()// OK
            t.mCPrivate()// 编译报错
        }
    }
}

类型变量 T 有交集类型 C & I,也就是与等价的超类在相同的作用域中声明的空类 CT 具有相同的成员。接口的成员总是 public 的,因此总是可以被继承(除非被覆盖),所以 mI 是 CT 和 T 的成员。在 C 的成员中,除了 mCPrivate 之外的成员都被 CT 继承了,因此也就是 CT 和 T 的成员。如果 C 与 T 在不同的保重,那么对 mCPackage 的调用将会产生一个编译时错误,因为这个成员在 T 被声明的地方是不可访问的。

ParameterizedType

ParameterizedType 表示一个参数化类型,例如 Collection<String>。
参数化类型是在反射方法第一次需要它时创建的,如此包中所指定的。当创建参数化类型 p 时,解析 p 实例化的泛型类型声明,并递归创建 p 的所有类型参数。

方法说明
getActualTypeArguments()返回表示此类型的实际类型参数的Type对象数组。注意,在某些情况下,返回的数组是空的。如果此类型表示嵌套在参数化类型中的非参数化类型,则可能发生这种情况
getRawType()返回表示声明此类型的类或接口的 Type 对象
getOwnerType()返回一个 Type 对象,该对象表示此类型所属的类型。例如,如果这种类型是O<T>.I<S>,返回 O<T&gt; 的表示形式。如果此类型是顶级类型,则返回 null

JLS(Java 语言规范) 4.5

泛型类或泛型接口的声明定义了一个参数化类型集。
参数化类型是形式为 C<T1,…,Tn> 的类或接口,其中 C 是泛型名,而 <T1,…,Tn> 是表示该泛型的特定参数化形式的类型参数列表。
泛型带有类型参数 E1,…,En,并且这些类型参数还带有相应的边界 B1,…,Bn。参数化类型的每个类型参数 Ti 都限定在相应的边界中列出的所有类型的任意子类型的范围内。也就是说,对于 B i 中的每一给边界类型 S,Ti 是 S[F1:=T1,…,Fn:=Tn] 的子类型
如果满足下列条件,那么参数化类型 C<T1,…,Tn> 就是良构的:

  • C 是泛型名
  • 类型参数的数量在 C 的泛型声明中的类型参数的数量相同
  • 当经过捕获转换并产生类型 C<X1,…,Xn> 后,对于每一给在 B1 中的边界类型 S, 每一个类型参数 Xi 都是 S[F1:=T1,…,Fn:=Tn] 的子类型

如果一个参数化类型不是良构的,那么就会产生一个编译错误。
在本规范中,无论何时提到类或接口类型,都包括泛化版本,除非明确将其排除。
如果两个参数化类型满足下列两个条件之一,就被认为是可证不同的:

  • 它们是对不同的泛型定义的参数化版本
  • 它们的任何类型参数都是可证不同的

正确参数化类型示例:

Seq<String>
Seq<Seq<String>>
Seq<String>.Zipper<Integer>
Pair<String, Integer>

不正确参数化类型示例:

Seq<int> // 不合法,简单类型不能当做类型参数
Pair<String> // 不合法,因为类型参数数量不够
Pair<String, String, String> // 不合法,类型参数数过多

参数化类型可以是对嵌套的泛型类或接口的参数化版本。例如,如果非泛型类 C 有一个泛型成员类 D<T&gt;,那么 C.D<Object> 就是一个参数化类型。并且如果泛型类 C<T> 有一个非泛型成员类 D,那么成员类型 C<String>.D 就是一个参数化类型,尽管类 D 不是泛型类。

4.5.1 参数化类型的类型参数

类型参数可以是引用类型或通配符。如果只要求提供类型参数的部分信息,那么通配符就很有了。

TypeArguments:
  <TypeArgumentList>

TypeArgumentList:
  TypeArgument{,TypeArgument}

TypeArgument:
  ReferenceType
  Wildcard
  
Wildcard:
  {Annotation} ? [WildcardBounds]
  
WildcardBounds:
  extends ReferenceType
  super ReferenceType

就像常规类型变量声明一样,可以指定通配符的明确边界。上界是通过下面的语法指定的,其中 B 是边界:

? extends B

与在方法签名中声明的普通类型变量不同,当时用通配符时,不需要任何类型推断。因此,通过下面的语法来声明通配符的下界是允许的,其中 B 是下界:

? super B

通配符 ? extends Object 等价于无界通配符 ?
如果两个类型参数满足下列两个条件之一,就被认为是可证不同的:

  • 参数既不是类型变量,也不是通配符,并且两个参数不是相同的类型
  • 其中一个类型参数是类型变量或通配符,且具有上界(来自捕获转换,如果这种转换是必要的)S;而另一个类型参数 T 不是类型变量或通配符,并且 |S| <: |T| 和 |T|<:|S| 都不成立(第4.8节和第4.10节)
  • 两个类型参数都是类型变量或通配符,且具有上界(来自捕获转换,如果这种转换是必要的)S 和 T,并且 |S| <: |T| 和 |T|<:|S| 都不成立(第4.8节和第4.10节)

在下列规则(其中 <: 表示子类型(第4.10节))的自反和传递闭包的范围内,如果 T2 所表示的类型集可证是 T1所表示的类型集的子集,那么我们就认为类型参数 T1 包含另一个类型参数 T2,记为 T2<= T1

无边界的通配符

class NoBoundWildcardDemo{
	static void printCollection(Collection<?> c){
		for(Object o : c) {
			System.out.println(o)}
	}
	public static void main(String[] args){
		Collection<String> cs = new ArrayList<>();
		cs.add("hello");
		cs.add("world")printCollection(cs)}
}

注意 如果使用 Collection<Object> 作为输入参数 C 的类型,那么这个方法的用处就会显得十分有限,因为它将只能通过具有 Collection<Object> 类型的参数表达式来调用。相反,如果使用无边界的通配符,将使得任意类型的 Collection 集合都可以作为参数。
下面的示例中,数组的元素类型就是通过通配符参数化的:

public Method getMethod(Class<?>[] parameterTypes){....}

有边界的通配符

boolean addAll(Collection<? extends E> c

这个方法声明在接口 Collection<E> 的内部,并且被设计为将输入参数中的所有元素添加到被调用该方法的结合对象中。一种很自然会想到的方法是使用 Collection<E> 作为 c 的类型,但其实并不需要如此严苛。另一种方法是将方法本生声明为泛型的:

<T> boolean addAll(Collection<T> c)

这个版本足够灵活,但是要注意,类型参数在签名中只用了一次。这反映了这样一个事实,即类型参数并未用来表示在参数类型与返回类型或抛出异常类型之间的任何相互依赖关系。当并不存在这种相互依赖时,泛型方法就并非好的选择,而是用通配符将是首先。

Reference(T referent, ReferenceQueue<? super T> queue)

其中 referent 可以被插入到任何队列中,只要该队列的元素类型是 referent 的类型 T 的超类型即可,而 T 就是通配符的下界。

4.5.2 参数化类型的成员和构造器

假设 C 是具有类型参数 A1,…,An 的泛型类或接口声明,而 C<T1,…,Tn> 是对 C 的参数化版本,其中 1<= i <= n, Ti 是类型(而不是通配符),那么:

  • 如果 m 是 C 中的成员或构造器声明,其声明的类型是 T,那么, m 在 C<T1,…,Tn> 中的类型就是 T[A1:=T1,…,An:=Tn]
  • 如果 m 是 D 中的成员或构造器声明,其中 D 是 C 扩展的类或实现的接口,并且如果 D<U1,…,Uk> 是 C<T1,…,Tn> 对应于 D 的超类型,那么,m 在 C<T1,…,Tn> 中的类型就是 m 在D<U1,…,Uk> 中的类型

如果 C 的参数化版本中任意一个或多个类型参数是通配符,那么:

  • 在 C<T1,…,Tn> 中的字段、方法和构造器的类型就是在 C<T1,…,Tn> 的捕获转换(第 5.1.10 节)中的字段、方法和构造器的类型
  • 如果 D 是 C 中的类或接口(可能是泛型的)声明,那么 D 在 C<T1,…,Tn> 中的类型就是 D,其中,如果 D 是泛型的,那么所有类型参数都是无界通配符。

这一点并不重要,因为不可能在不执行捕获转换的情况下访问参数化类型的成员,并且也不可能在类实例创建表达式中在 new 关键字之后使用通配符类型。
前面这段华的唯一列外是将嵌套的参数化类型用作 instanceof 操作符中的表达式,这时捕获转换是不可用的。

在泛型声明中声明的 static 成员必须使用对应于该泛型的非泛型来引用,否则就会产生编译时的错误。
换句话说,使用参数化类型来引用在泛型声明中声明的 static 成员是非法的。

class Foo<T>{
	public static int classVal = 42}
// 下面赋值是不合法的
Foo<String>.classValu = 91// 应该写成:
Foo.classVal = 91

WildcardType

WildcardType 表示通配符类型表达式,例如 ?? extends Number,还是 ? super Integer

方法描述
getUpperBounds()返回一个表示此类型变量的上界的 Type 对象数组。注意,如果没有显式声明上界,上界就是 Object。对于每个上界 B:如果 B 是一个参数化类型或类型变量,它将被创建,否则,B 被解析
getLowerBounds()返回一个表示此类型变量的下界的 Type 对象数组。注意,如果没有明确声明下界,那么下界就是 null 类型。在这种情况下,将返回一个长度为零的数组。对于每个下界B:如果 B 是一个参数化类型或类型变量,它将被创建,否则,B 被解析

AnnotatedElement

  • 表示当前在此 VM(虚拟机) 中运行的程序的注解元素。这个接口允许以反射方式读取注解。该接口中方法返回的所有注解都是不可变和可序列化的。调用方可以修改该接口的方法返回的数组,而不会影响返回给其他调用方的数组。

  • getAnnotationsByType(Class) 和 getDeclaredAnnotationsByType(Class) 方法支持一个元素上的多个相同类型的注解。如果任意一个方法的参数是可重复注解类型(Java 语言规范 9.6),那么该方法将“查看”容器注解(Java 语言规范 9.7),如果存在,并返回容器内的任何注解。容器注解可以在编译时生成,以封装参数类型的多个注解。

  • 在这个接口中,直接出现(directly present)、间接出现(indirectly present)、出现(present)和关联(associated)的术语被用来精确描述方法返回的注解:

    • 注解 A 直接出现在元素 E 上,如果元素 E 具有 RuntimeVisibleAnnotations 或 RuntimeVisibleParameterAnnotations 或RuntimeVisibleTypeAnnotations 属性,该属性包含属性 A。
    • 注解 A 是间接地出现在一个元素 E 如果 E 具有 RuntimeVisibleAnnotations 或 RuntimeVisibleParameterAnnotations RuntimeVisibleTypeAnnotations 属性,并且 A 的类型是可重复的同时该属性恰好包含一个注解,其值元素包含 A,其类型为 A 的类型所包含的注解类型。
    • 如果有注解 A 出现(present)在元素 E 上:
      • A 直接出现在 E 上
      • A 的类型的注解不直接出现在 E 上,E 是一个类,A 的类型是可继承的,A 出现在 E 的超类上。
    • 如果注解 A 与元素 E 相关联(associated):
      • A 直接或间接出现在 E 上
      • A 的类型的注解不直接或者间接出现在 E 上,E 是一个类, A 的类型是可继承的, A 出现在 E 的超类上
  • 下表总结了该接口中出现的不同方法的注解类型。概述不同AnnotatedElement方法检测到的存在类型

    概述不同 AnnotatedElement 方法检测到的存在类型
    Kind of Presence
    MethodDirectly PresentIndirectly PresentPresentAssociated
    TgetAnnotation(Class<T>)
    Annotation[] getAnnotations()
    T[] getAnnotationsByType(Class<T>)
    T getDeclaredAnnotation(Class<T>)
    Annotation[] getDeclaredAnnotations()
    T[]getDeclaredAnnotationsByType(Class<T>)
  • 对于 get[Declared]AnnotationsByType(Class < T >) 的调用,直接或间接出现在元素 E 上的注解按顺序计算,就像 E 上间接出现的注解直接出现在 E 上,代替它们的容器注解一样。按它们在容器注解的 value 元素中出现的顺序。

  • 如果注解类型 T 最初是不可重复的,后来又被修改为可重复的,那么有几个兼容性问题需要记住。包含 T 的注解类型是 TC。

    • 将 T 修改为可重复的源代码和二进制文件与 T 的现有用法和 TC 的现有用法兼容。也就是说,为了源代码兼容性,带有 T 类型注解或 TC 类型注解的源代码仍然可以编译。为了二进制兼容性,带有 T 类型注解或 TC 类型注解(或带有 T 类型注解或 TC 类型注解的其他类型)的类文件如果链接到早期版本,将链接到修改后的 T 版本。(注解类型 TC 在 T 被修改为形式上可重复之前可以非正式地充当包含注解类型的行为。或者,当 T 可重复使用时,TC 可以作为一种新类型引入。)

    • 如果一个注解类型 TC 出现在一个元素上,并且 T 被修改为可重复的包含 TC 的注解类型,那么

      • 对 T 的更改在行为上与 get[Declared]Annotation(Class<T>)(使用 T 或 TC 的参数调用)和 get[Declared]Annotation() 方法兼容,因为方法的结果不会因为 TC 成为 T 的包含注解类型而改变。
      • 对 T 的更改会改变 get[Declared]AnnotationsByType(Class<T>) 方法的调用结果,该方法的参数为 T,因为这些方法现在将识别类型 TC 的注解为 T 的容器注解,并将“查看”它以公开类型 T 的注解。
    • 如果一个元素上有一个类型为 T 的注解,并且 T 是可重复的,并且添加了更多类型为 T 的注解

      • 类型 T 注解的添加是源代码兼容和二进制兼容的。
      • 类型 T 注解的添加改变了 get[Declared]Annotation(Class<T>) 方法和 get[Declared]Annotation() 方法的结果,因为这些方法现在只会看到元素上的容器注解,而不会看到类型 T 的注解。
      • 类型 T 注解的添加改变了 get[Declared]AnnotationsByType(Class<T>) 方法的结果,因为它们的结果将公开类型 T 的附加注解,而以前它们只公开一个类型 T 的注解。
  • 如果一个方法返回的注解在此接口中包含 Class-valued 成员(直接或间接)指的是一个无法访问的类在这个 VM,试图读类通过调用相关 Class-returning 方法返回的注解将导致 TypeNotPresentException。

  • 类似地,如果注解中的枚举常量不再出现在枚举类型中,尝试读取枚举值成员将导致 EnumConstantNotPresentException。

  • 如果注解类型 T 被 @Repeatable 注解标注,该注解的 value 元素指示类型 TC,但是 TC 没有声明返回类型 T[] 的 value() 方法,则抛出类型 AnnotationFormatError 的异常。

  • 最后,尝试读取定义不兼容的成员将导致 AnnotationTypeMismatchException 或 IncompleteAnnotationException。

方法作用
isAnnotationPresent(Class<? extends Annotation>)如果在此元素上存在指定类型的注解,则返回 true,否则返回 false
getAnnotation(Class<T>)如果存在指定类型的元素注解,则返回该元素的注解,否则为空
getAnnotations()返回存在于此元素上的注解。如果此元素上没有z注解,则返回值为长度为0的数组。这个方法的调用者可以随意修改返回的数组;它对返回给其他调用者的数组没有影响
getAnnotationsByType(Class<T>)返回与此元素关联的注解。如果没有与此元素相关的注解,则返回值是长度为0的数组。该方法和 getAnnotation(Class) 之间的区别在于,该方法检测其参数是否为可重复注解类型(JLS 9.6),如果是,则尝试通过“查看”容器注解来找到该类型的一个或多个注解。这个方法的调用者可以随意修改返回的数组;它对返回给其他调用者的数组没有影响
getDeclaredAnnotation(Class<T>)如果指定类型的注解直接存在,则返回该元素的注释,否则为null。此方法忽略继承的注释。(如果该元素上没有直接的注释,则返回null)
getDeclaredAnnotations()返回直接出现在此元素上的注解。此方法忽略继承的注解。如果该元素上没有直接的注解,则返回值是长度为0的数组。这个方法的调用者可以随意修改返回的数组;它对返回给其他调用者的数组没有影响

AnnotatedType

AnnotatedType 表示该虚拟机中当前运行的程序中某个类型的潜在注解使用。可以使用 Java 编程语言中的任何类型,包括数组类型、参数化类型、类型变量或通配符类型。

方法作用
getType()返回此注释类型所表示的底层类型

GenericDeclaration

所有声明类型变量的实体的公共接口

方法作用
getTypeParameters()返回一个 TypeVariable 对象数组,该数组表示由此 GenericDeclaration 对象所表示的泛型声明所声明的类型变量,按声明顺序排列。如果基础泛型声明没有声明类型变量,则返回长度为 0 的数组

AccessibleObject

AccessibleObject 类是字段、方法和构造函数对象的基类。它提供了在使用反射对象时将其标记为禁止默认的 Java 语言访问控制检查的能力。当 Fields、Methods 或 Constructors 分别用于设置或获取字段、调用方法或创建和初始化类的新实例时,执行访问检查(公共、默认(包 package)访问、保护和私有成员)。
在反射对象中设置可访问标志允许具有足够特权的复杂应用程序(如 Java 对象序列化或其他持久性机制)以通常禁止的方式操作对象。默认情况下,反射对象是不可访问的。

字段作用
Permission ACCESS_PERMISSION = new ReflectPermission(“suppressAccessChecks”)Permission 对象,用于检查客户端是否有足够的权限来阻止 Java 语言访问控制检查
boolean override指示是否覆盖语言级别的访问检查
方法作用
setAccessible(AccessiibleObject[], boolean)方便方法,通过单个安全检查(为了效率)为对象数组设置可访问标志
setAccessible(boolean)将此对象的可访问标志设置为指定的布尔值。如果值为 true,则表示使用反射对象时应该禁止 Java 语言访问检查。值为 false 表示反射的对象应该强制执行Java语言访问检查

Member

成员(Member)是反映关于单个成员(字段或方法)或构造函数的标识信息的接口。

字段作用
int PUBLIC = 0标识类或接口的所有公共成员的集合,包括继承成员
int DECLARED = 1标识类或接口的所有定义的成员的集合,不包括继承成员
方法作用
getDeclaringClasss()返回表示声明该成员所表示的成员或构造函数的类或接口的 Class 对象
getName()返回此成员所表示的底层成员或构造函数的简单名称
getModifiers()以整数形式返回由该成员表示的成员或构造函数的 Java 语言修饰符。Modifier 类应该用于解码整数中的修饰符
isSynthetic()如果该成员是由编译器引入的,则返回 true ;否则返回 false

Field

在这里插入图片描述

  • Field 提供关于类或接口的单个字段的信息和动态访问。反射的字段可以是类(静态)字段或实例字段。
  • Field 允许在获取或设置访问操作期间发生扩展转换,但如果发生收缩转换,则抛出 IllegalArgumentException。
字段作用
Class<?> clazz字段所在的类
String name字段名称
Class<?> type字段类型
int modifiers字段修饰符
FieldRepository genericInfo泛型信息存储库;延迟初始化
方法作用
get(Object)返回指定对象上由该字段表示的字段的值。如果该值具有基元类型,则该值将自动封装在对象中。如果底层字段是静态字段,Object 参数将被忽略;它可以是 null
getGenericType()返回一个 Type 对象,该对象表示此 Field 对象所表示的字段的声明类型。如果 Type 是参数化的类型,则返回的 Type 对象必须准确地反映源代码中使用的实际类型参数。如果底层字段的类型是类型变量或参数化类型,则创建它。否则,就解析
isEnumConstant()如果此字段表示枚举类型的元素,则返回 true;否则返回 false

Parameter

关于方法参数的信息。参数提供关于方法参数的信息,包括它的名称和修饰符。它还提供了获取参数属性的另一种方法。

字段作用
String name参数名称
int modifiers修饰符
Executable executable定义参数的 Executable 对象
int index参数索引
方法作用
isImplicit()如果此参数在源码中隐式声明,则返回 true;否则返回 false
isNamedPresent()如果形参的名称与类文件一致,则返回 true;否则返回 false。参数是否有名称由声明该参数的方法的 MethodParameters 属性决定
getName()返回参数的名称。如果参数的名称存在,则此方法返回类文件提供的名称。否则,该方法将合成一个形式为 argN 的名称,其中 N 是声明参数的方法的描述符中参数的索引
getParameterizedType()返回一个 Type 对象,该对象标识此 Parameter 对象所表示的参数的参数化类型
getType()返回一个 Class 对象,该对象标识由此 Parameter 对象表示的参数声明的类型
getAnnotatedType()返回一个 AnnotatedType 对象,该对象表示使用类型来指定由此参数表示的形式参数的类型
isSynthetic()如果此参数没有在源代码中隐式或显式声明,则返回 true;否则返回false
isVarArgs()如果此参数表示一个变量参数列表,则返回true;否则返回false
getModifiers()获取此 Parameter 对象所表示的参数的修饰符标志

Executable

在这里插入图片描述

Method 和 Constructor 的公共功能的共享超类。

方法作用
getParameterTypes()返回一个 Class 对象数组,该数组按声明顺序表示该对象所表示的 Executable 形式参数类型。如果底层 Executable 不接受参数,则返回长度为 0 的数组
getParameterCount()返回该对象表示的 Executable 形式参数的数量(无论是显式声明还是隐式声明)
getGenericParameterTypes()返回一个 Type 对象数组,该数组按声明顺序表示该对象所表示的 Executable 的形式参数类型。如果底层 Executable 不接受参数,则返回长度为 0 的数组。如果形式参数类型是参数化类型,则为其返回的 Type 对象必须准确地反映源代码中使用的实际类型参数。如果形式参数类型是类型变量或参数化类型,则创建它。否则,就解决了
getParameters()返回一个 Paramete r对象数组,该数组表示由此对象表示的底层可执行文件的所有参数。如果 Executable 没有参数,则返回长度为 0 的数组。底层 Executable 的参数不一定具有唯一的名称,或者在 Java 编程语言(JLS 3.8)中是合法标识符的名称
getExceptionTypes()返回一个 Class 对象数组,该数组表示由此对象表示的底层 Executable 声明抛出的异常类型。如果 Executable 在其 throws 子句中没有声明异常,则返回长度为 0 的数组
getGenericExceptionTypes()返回一个 Type 对象数组,表示此可 Executable 对象声明要抛出的异常。如果底层 Executable 在其抛出子句中没有声明异常,则返回长度为 0 的数组。如果异常类型是类型变量或参数化类型,则创建异常类型。否则,就解决了
isVarArgs()如果此 Executable 被声明为带多个可变参数,则返回 true;否则返回 false
getParameterAnnotations()返回一个由 Annotation 数组组成的数组,该数组按声明顺序表示由此对象表示的 Executable 形参上的注解。合成参数和强制参数(参见下面的解释),例如内部类构造函数的外部 this 参数将在返回的数组中表示。如果 Executable 没有参数(意味着没有形参的、合成的和强制的参数),将返回一个 0 长度的数组。如果 Executable 有一个或多个参数,则为每个参数返回长度为 0 的嵌套数组,不带注解。返回的数组中包含的注解可序列化的对象。此方法的调用者可以自由修改返回的数组;它对返回给其他调用者的数组没有影响。编译器可以在方法的形参列表中添加源文件中隐式声明的额外形参(强制),以及源文件中既没有隐式声明也没有显式声明的形参(合成)
getAnnotatedReturnType()返回一个 AnnotatedType 对象,该对象表示使用类型来指定由此 Executable 表示的方法/构造函数的返回类型。如果这个Executable 对象代表一个构造函数,那么 AnnotatedType 对象代表所构造对象的类型。如果这个 Executable 对象表示一个方法,那么 AnnotatedType 对象表示使用一个类型来指定方法的返回类型
getAnnotatedReceiverType()返回一个 AnnotatedType 对象,该对象表示使用类型来指定此 Executable 对象所表示的方法/构造函数的接收类型。只有当方法/构造函数有一个接收参数时,方法/构造函数的接收类型才可用(JLS 8.4.1)。如果这个 Executable 对象表示一个没有接收参数的构造函数或实例方法,或者在其类型上有一个没有注解的接收参数,则返回值是一个 AnnotatedType 对象,它表示一个没有注解的元素。如果这个 Executable 对象代表一个静态方法,则返回值为 null
getAnnotatedParameterTypes()返回一个 AnnotatedType 对象数组,该对象表示使用类型来指定此 Executable 所表示的方法/构造函数的x形式参数类型。数组中对象的顺序对应于方法/构造函数声明中形参类型的顺序。如果方法/构造函数没有声明参数,则返回长度为 0 的数组

Method

在这里插入图片描述

  • 方法提供关于类或接口上单个方法的信息和访问。反射的方法可以是一个类方法或一个实例方法(包括一个抽象方法)
  • 当将要调用的实际参数与底层方法的形式参数匹配时,方法允许进行扩展转换,但如果发生收缩转换,则抛出 IllegalArgumentException
字段作用
Class<?> clazz定义方法的类
int modifiers修饰符
Class<?> returnType返回值类型
Class<?> [] parameterTypes参数类型
方法作用
getReturnType()返回一个 Class 对象,该对象表示此 Method 对象所表示的方法的正式返回类型
geGenericReturnType()返回一个 Type 对象,该对象表示此 Method 对象所表示的方法的正式返回类型。如果返回类型是参数化类型,则返回的 Type 对象必须准确地反映源代码中使用的实际类型参数。如果返回类型是类型变量或参数化类型,则创建它。否则,就解决了
isBridge()如果此方法是桥接方法,则返回 true;否则返回 false
isDefaultt()如果此方法为默认方法,则返回 true 否则返回 false。默认方法是一个公共非抽象实例方法,即在接口类型中声明的具有主体的非静态方法
getDefaultValue()返回此 Method 实例所表示的注解成员的默认值。如果成员是原始类型的,则返回相应包装器类型的实例。如果没有默认值与成员相关联,或者如果方法实例不表示注释类型的声明成员,则返回 null
invoke(Object, Object...)在具有指定参数的指定对象上调用此 Method 对象表示的基础方法。各个参数会自动展开以匹配基本形式参数,基本参数和引用参数都需要进行方法调用转换。如果底层方法是静态的,那么指定的 Object… 参数将被忽略。它可以是null。如果底层方法所需的形参数为 0,则提供的 args 数组的长度可能为 0 或 null。如果底层方法是一个实例方法,它将使用动态方法查找调用,如 Java 语言规范第二版第 15.12.4.4 节所述;特别是,将基于目标对象的运行时类型进行重写。如果底层方法是静态的,如果它还没有初始化,那么声明该方法的类将被初始化。如果方法正常完成,它返回的值将返回给 invoke 的调用者;如果值具有原始类型,则首先将其适当地包装在对象中。但是,如果该值的类型是基元类型的数组,则数组的元素不会封装在对象中;换句话说,返回一个基本类型的数组。如果基础方法返回类型为 void,则调用返回 null

JLS(Java 语言规范) 15.12.4
在运行时,方法调用需要五个步骤。

  1. 可能会计算目标引用
  2. 计算参数表达式
  3. 检查被调用方法的可访问性
  4. 定位待执行的方法的实际代码
  5. 创建新的激活帧,如果需要,还会执行同步,然后将控制流转移到该方法代码

Constructor

在这里插入图片描述

构造函数提供关于类的单个构造函数的信息和访问。当将 newInstance() 的实参与底层构造函数的形参匹配时,构造函数允许进行扩展转换,但如果发生收缩转换,则抛出 IllegalArgumentException。

字段作用
Class<?> clazz定义构造器的类
int modifiers修饰符
Class<?> [] parameterTypes参数类型
方法作用
newInstance(Object…)使用指定的初始化参数创建并初始化构造函数声明类的新实例。各个参数会自动拆箱以匹配基本形参,基本形参和引用参数都需要进行方法调用转换。如果底层构造函数所需的形参数为 0,则提供的i数组的长度可能为 0 或 null。如果构造函数声明的类是非静态上下文中的内部类,则构造函数的第一个实参必须是封闭实例;参见 Java 语言规范的 15.9.3 节。如果所需的访问和参数检查成功,实例化将继续进行,如果构造函数的声明类尚未初始化,则初始化它。如果构造函数正常完成,则返回新创建并初始化的实例
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿大叔文海

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值