反射

1.1    Java反射概述

反射(Reflection)机制是Java语言特性之一,是Java被视为动态(或准动态)语言的一个关键特性。

1.1.1    什么是反射

在计算机领域,反射指一种能力,能够自描述和自控制,即在运行状态中,动态获取类信息及动态调用实例方法的能力。

Java反射有以下3个动态特性。

▶    运行时创建实例。

▶    运行期间调用方法。

▶    运行时更改属性。

如何理解Java的反射机制呢?首先来回顾一下Java程序的执行过程。Java程序要想运行,Java类必须被Java虚拟机加载。

之前我们所运行的程序都是在编译时就已经链接了所有所需的类,而Java反射机制则允许程序在运行时再加载、探知、使用那些在编译时完全未知的类。例如,在之前课程中使用JDBC时,使用Class.forName()方法通过一个字符串形式的类名查找并加载驱动类,就是对反射机制的初步运用。每个项目中使用的数据库产品和版本都不是一成不变的,在代码中用new关键字实例化驱动类的传统做法是不明智的,而利用反射机制则可以在运行时读取配置文件中的驱动类名,动态加载所需的驱动类。

反射机制允许Java程序加载一个运行时才得知其名称的类,获悉其完整API信息,包括其修饰符(诸如public、static等)、超类、实现的接口,也包括属性和方法的所有信息;并可生成其实例、对其属性赋值或调用其方法。通过Java反射可以实现以下功能。

▶    在运行时探知任意一个实例所属的类。

▶    在运行时构造任意一个类的实例。

▶    在运行时探知任意一个类所具有的方法和属性。

▶    在运行时调用任意一个实例的方法。

就像照镜子能够看清自己,反射使程序可以看清一个类的情况并加以使用。Java反射机制能够探知类的基本结构,这种对Java类结构探知的能力,称为Java类的“自审”。并且,反射机制是构建框架技术的基础所在,掌握Java反射机制,对以后学习框架技术有很大的帮助。

1.1.2    Java反射常用API

使用Java反射技术,常用的类如下。

▶    java.lang.Class<T>类:反射的核心类,反射所有的操作都是围绕该类来生成的。通过Class类可以获取类的属性、方法等内容信息。

▶    java.lang.reflect.Constructor<T>类:表示类的构造方法。

▶    java.lang.reflect.Field类:表示类的属性,可以获取和设置类中属性的值。

▶    java.lang.reflect.Method类:表示类的方法,可以用来获取类中方法的信息或执行方法。

1.2    反射的的应用

在Java程序中使用反射的基本步骤如下。

(1)导入java.lang.reflect包中的相关类。

(2)获得需要操作的类的Class实例。

(3)调用Class实例的方法获取Field、Method等实例。

(4)使用反射API操作实例成员。

1.2.1    获取类的信息

1.    获取Class实例

▶    调用类或接口实例的getClass()方法。

Class clz = obj.getClass(); // obj为某个类型的实例

▶    调用类或接口的class属性。

Class clz = Student.class; // Student 为自定义的学生类型

▶    使用Class.forName()方法。

Class clz = Class.forName("com.mysql.cj.jdbc.Driver");

2.    从Class实例获取信息

在获得了某个类型对应的Class实例之后,就可以调用Class实例的方法来获得该类型的信息。Class类提供了大量实例方法来获取对应类型的详细信息。

▶    获取对应类型的基本信息,相关方法:获取对应类型的基本信息的方法:方法名:String getName(),说明:以字符串形式返回该类型的名称。方法名:String getSimpleName(),说明:以字符串形式返回该类型的简称。方法名:Package getPackage(),说明:获取该类型所在的包。方法名:Class getSuperclass(),说明:返回该类型的超类的Class实例。方法名:Class[] getInterfaces(),说明:返回该类型所实现的全部接口的Class实例。方法名:int getModifiers(),说明:返回该类型的所有修饰符,由public、protected、private、final、static、abstract等对应的int常量组成,返回的整数应使用Modifier工具类来解码,才可以判断修饰符的构成。方法名:Class[] getDeclaredClasses(),说明:返回该类型中包含的全部内部类的Class实例,方法名:Class getDeclaringClass(),说明:返回该类型所在的外部类的Class实例。

1.2.2    创建实例

通过反射来创建Java类型的实例有如下两种方式。

▶    使用Class实例的newInstance()方法创建相关类型的实例。

▶    使用Constructor实例创建相关类型的实例。

1.2.3    访问类的属性

使用Field实例可以对属性进行取值或赋值操作,主要方法:访问属性的方法:方法:xxx getXxx(Object obj),说明:xxx表示8种基本数据类型之一,如int getInt(Object obj)。obj为该属性所在类的实例。假设instance表示A类的实例,field表示A类中的属性a,则field.getInt(instance)表示以int类型返回instance中属性a的值。若Field实例表示的是一个静态属性,则obj可以设置为null。方法:Object get(Object obj),说明:以Object类型返回obj中相关属性的值。方法:void setXxx(Object obj, xxx val),说明:将obj中相关属性的值设置为val。xxx为8种基本数据类型之一。方法:void set(Object obj,Object val),说明:将obj中相关属性的值设置为val。方法:void setAccessible(boolean flag),说明:对相关属性设置访问权限。设置为true可以禁止Java语言访问检查。

1.2.4    调用类的方法

Method类中包含一个invoke()方法,通过invoke()方法,Method实例可以调用Java类的实例方法和静态方法。invoke()方法定义如下:

                  Object invoke(Object obj, Object... args);

其中,obj是执行该方法的对象,args是执行该方法时传入的参数。

例如,method表示A类中的fun()方法,instance是A类的实例,则method.invoke(instance,args)表示调用instance的fun()方法并传入参数args。

若Method实例表示的是一个静态方法,则obj可以为null。

本章总结

◎    Java反射机制是指在运行状态中,动态获取类型信息及动态访问实例成员的能力。

◎    使用反射可以在程序运行时创建类的实例及访问其属性和方法。

◎    反射在Java框架技术中有着大量的应用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容