欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java从入门到精通_学习笔记17(反射)

程序员文章站 2022-06-30 22:55:10
...

Class类与Java反射

通过Java反射机制,可以在程序中访问已经装载到JVM中的Java对象的描述,实现访问、检测和修改描述Java对象本身信息的功能。Java反射机制的功能十分强大,在java.lang.reflect包中提供了对该功能的支持。


所有Java类均继承了Object类,在Object类中定义了一个getClass()方法,该方法返回一个类型为Class的对象。利用Class类的对象,可以访问getClass()方法返回的该对象的描述信息。
Java从入门到精通_学习笔记17(反射)
注:

  • 在通过getFields()和getMethods()方法依次获得权限为public的成员变量和方法时,将包含从超类中继承到的成员变量和方法;而通过方法getDeclaredFields()和getDeclaredMethods()只是获得在本类中定义的所有成员变量和方法。

1. 访问构造方法

通过下列一组方法访问类的构造方法:

  • getConstructors()
  • getConstructor(Class<?>…parameterTypes)
  • getDeclaredConstructors()
  • getDeclaredConstructor(Class<?>…parameterTypes)

注:每个Constructor对象代表一个构造方法,利用Constructor对象可以操纵相应的构造方法。


如果是访问指定的构造方法,需要根据该构造方法的入口参数的类型来访问。例如,访问一个入口参数类型依次为String和int型的构造方法,通过下面两种方式均可实现。

objectClass.getDeclaredConstructor(String.class , int.class);
objectClass.getDeclaredConstructor(new Class[]{String.class , int.class});

Java从入门到精通_学习笔记17(反射)
通过java.lang.reflect.Modifier类可以解析出getModifiers()方法的返回值所表示的修饰符信息,在该类中提供了一系列用来解析的静态方法,既可以查看是否被指定的修饰符修饰,还可以以字符串的形式获得所有修饰符。
Java从入门到精通_学习笔记17(反射)

2. 访问成员变量

在通过下列一组方法访问成员变量:

  • getFields()
  • getField(String name)
  • getDeclaredFields()
  • getDeclaredField(String name)

注:每个Field对象代表一个成员变量,利用Field对象可以操纵相应的成员变量。


**如果是访问指定的成员变量,可以通过该成员变量的名称来访问。**例如,访问一个名称为birthday的成员变量,访问方法如下:

object.getDeclaredField("birthday");

Java从入门到精通_学习笔记17(反射)

3. 访问方法

通过下列一组方法访问方法:

  • getMethods()
  • getMethod(String name, Class<?>…parameterTypes)
  • getDeclaredMethods()
  • getDeclaredMethod(String name, Class<?>…parameterTypes)

注:每个Method对象代表一个方法,利用Method对象可以操纵相应的方法。
Java从入门到精通_学习笔记17(反射)


如果是访问指定的方法,需要根据该方法的名称和入口参数的类型来访问。 例如,访问一个名称为print、入口参数类型依次为String和int型的方法,通过下面两种方式均可实现:

  • objectClass.getDeclaredMethod(“print”, String.class, int.class);
  • objectClass.getDeclaredMethod(“print”, new Class[ ] {String.class, int.class });

使用Annotation功能

Java中提供了Annotation功能,该功能可用于类、构造方法、成员变量、方法、参数等的声明中。该功能并不影响程序的运行,但是会对编译器警告等辅助工具产生影响。

1. 定义Annotation类型

在定义Annotation类型时,也需要用到用来定义接口的interface关键字,但需要在interface关键字前加一个“@”符号,即定义Annotation类型的关键字为@interface,这个关键字的隐含意思是继承了java.lang.annotation.Annotation接口。


代码演示:

// 无任何成员
public @interface NoMemberAnnotation{
}
// 包含多个成员
public @interface NoMemberAnnotation{
	String describe();
	Class type();
}
// 为成员设置默认值
public @interface NoMemberAnnotation{
	String describe() default"<默认值>";
	Class type() default void.class;
}

通过Annotation类型@Target来设置Annotation类型适用的程序元素种类:
Java从入门到精通_学习笔记17(反射)


通过Annotation类型@Retention可以设置Annotation的有效范围:
Java从入门到精通_学习笔记17(反射)

2. 访问Annotation信息

  • 如果在定义Annotation类型时将@Retention设置为RetentionPolicy.RUNTIME,那么在运行程序时通过反射就可以获取到相关的Annotation信息,如获取构造方法、字段和方法的Annotation信息。
  • 类Constructor、Field和Method均继承了AccessibleObject类,在AccessibleObject中定义了3个关于Annotation的方法,其中方法isAnnotationPresent(Class<? extends Annotation> annotationClass)用来查看是否添加了指定类型的Annotation,如果是则返回true,否则返回false;方法getAnnotation(ClassannotationClass)用来获得指定类型的Annotation,如果存在则返回相应的对象,否则返回null;方法getAnnotations()用来获得所有的Annotation,该方法将返回一Annotation数组。
  • 在类Constructor和Method中还定义了方法getParameterAnnotations(),
    用来获得为所有参数添加的Annotation,将以Annotation类型的二维数组返回,在数组中的顺序与声明的顺序相同,如果没有参数则返回一个长度为0的数组;如果存在未添加Annotation的参数,将用一个长度为0的嵌套数组占位。