第十六章 反射与注释

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

众所周知,所有Java类均继承了Object 类,在Object类中定义了一个getClass()方法,该方法返回一个类型为Class的对象。例如下面的代码:

JTextField textField =new JTextField();

//创建 JTextField 对象

 Class textFieldC = textField.getClass();

//获取 Class 对象 

利用 Class类的对象textFieldC,可以访问用来来返回该对象的textField对象的描述信息。

16.1.1 访问构造方法
在通过下列一组方法访问构造方法时,将返回Constructor类型的对象或数组。每个Constructor 对象代表一个构造方法,利用Constructor对象可以操纵相应的构造方法:

①getConstructors()。

②getConstructor(Class...parameterTypes)。 ③getDeclaredConstructors()。

④getDeclaredConstructor(Class...parameterTypes)。

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

objectClass.getDeclaredConstructor(String.class, int.class);

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

通过java.lang.reflect.Modifier类可以解析出 ge tModifiers()方法的返回值所表示的修饰符信息,在该类中提供了一系列用来解析的静态方法,既能查看是否被指定的修饰符修饰,又能以字符串的形式获得所有修饰符。

例如,判断对象constructor所代表的构造方法去是否被private 修饰,以及以字符串形式获得该构造方法的所有修饰符的典型代码如下:

int modifiers = constructor. getModifiers();

boolean isEmbellishByPriv ate= Modifier.isPrivate(modifiers);

String embellishment =Mo difier.toString(modifiers);

【例16.1】反射一个类的所有构造方法

在 com.mr包下创建一个Demo1类,在该类中声明一个 String型成员变量和3个int型成员变量,并提供3个构造方法。具体代码如下:

第十六章 反射与注释_第1张图片

第十六章 反射与注释_第2张图片

第十六章 反射与注释_第3张图片 

  16.1.2 访问成员变量
在通过下列一组方法访问成员变量时,*将返回 Field 类型的对象或数组。每个Field对象代表一个成员变量,利用Field对象可以操纵相应的成员变量:

①getFields()。

②getField(String name)。

③getDeclaredFields()。

④getDeclaredField(String name)。

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

object. getDeclaredField("birthday");

【例16.2】反射一个类的所有成员变量量

在 com.mr包下创建一个Demo2类,在该类中依次声明一个int、float、boolean和String型的成员变量,并将它们设置为不同的访问权限。具体代码如下:

第十六章 反射与注释_第4张图片

第十六章 反射与注释_第5张图片

第十六章 反射与注释_第6张图片

 

16.1.3 访问成员方法
在通过下列一组方法访问成员方法时,将返回 Method类型的对象或数组。每个Method对象代表一个方法,利用Method对象可以操纵相应的方法去:

①getMethods()。

②getMethod(String name, Class...parame eterTypes)。

③getDeclaredMethods()。

④getDeclaredMethod(String name, Class...parameterTypes)

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

objectClass.getDeclaredMethod("print", String.class s, int.class);

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

【例16.3】反射一个类的所有成员方法

在com.mr 包下创建一个Demo3类,并编写4个成员方法。具体代码如下:

第十六章 反射与注释_第7张图片

第十六章 反射与注释_第8张图片

第十六章 反射与注释_第9张图片

第十六章 反射与注释_第10张图片 

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

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

public @interface NoMemberAnnotation {

上面定义的 Annotation 类型@NoMemberA nnotation 未包含任何成员,这样的Annotation类型被称为 marker annotation.下面的代码定义了一个只只包含一个成员的Annotation类型:

public @interface OneMemberAnnotation {

          String value();

}

①String:成员类型。可用的成员类型有String、Class、primitive、enumerated和annotation,以及所列类型的数组。

②value: 成员名称。如果在所定义的Annotation类型中只包含一个成员,通常将成员名称命名为value。

下面的代码定义了一个包含多个成员的Annotation类型:

public @interface MoreMemberAnnotation {

         String describe();

         Class type();

}

在为Annotation类型定义成员时,也可以为成员设置默认值。例如,下面的代码在定义Annotation类型时就为成员设置了默认值:

public @interface DefaultValueAnnotation {

         String describe() default "<默认值>";

        Class type() default void.class;

}

在定义Annotation类型时,还可以通过 Annotation类型@Target来设置Annotation类型适用的程序元素种类。如果未设置@Target,则表示适用于所有程序元素。

通过 Annotation类型@Retention可以设置 Annotation 的有效范围。枚举类RetentionPolicy中的枚举常量用来设置@Retention,如果未设置@Retention,Annotation的有效范围为枚举常量 CLASS 表示的范围。

【例16.4】创建自定义的注解

首先定义一个用来注释构造方法的Annotatio n类型@Constructor_Annotation,有效范围为在运行时加载 Annotation到JVM 中。完整代码如下:

第十六章 反射与注释_第11张图片

第十六章 反射与注释_第12张图片

第十六章 反射与注释_第13张图片 

 16.2.2 访问 Annotation 信息 
如果在定义Annotation类型时将@Retention设置为RetentionPolicy.RUNTIME,那么在运行程序时通过反射就可以获取到相关的Annotation信息,如获取构造方法、字段和方法的Annotation信息。

Constructor 类、Field 类和Method类均继承了AccessibleObject类,在AccessibleObject中定义了3个关于Annotation的方法。其中,方法isAnnotationPresent(Class annotationClass)用来查看是否添加了指定类型的Annotation,如果是则返回true,否则返回false;方法getAnnotation(Class annotationClass)用来获得指定类型的Annotation,如果存在则返回相应的对象,否则返回null;方法getAnnotations()用来获得所有的Annotation,该方法将返回一个Annotation数组。

在onstructor类和Method类中还定义了方法getParameterAnnotations(),用来获得为所有参数添加的 Annotation,将以Annotation类型的二维数组返回,在数组中的顺序与声明的顺序相同。如果没有参数则返回一个长度为0的数组;如果存在未添加Annotation的参数,将用一个长度为0的嵌套数组占位。

【例16.5]访问注释中的信息

实现在程序运行时通过反射访问Record类中的Annotation信息。首先编写访问构造方法及其包含参数的Annotation信息的代码。关键代码如下:

 第十六章 反射与注释_第14张图片

你可能感兴趣的:(java)