前言

最近在接触 Android 的组件化原理的时候,发现自己对 Java 反射的机制理解并不是很深,只能利用周末的时间把 Java 反射机制回炉重铸。

什么是Java反射

反射机制是 Java 语言提供的一种基础功能,赋予了 Java 程序在运行时的自省(introspect,官方用语)的能力。通过 Java 的反射机制,程序员可以在 Java 程序在运行态的时候操作任意的类或者对象的属性、方法。利用 Java 的反射机制,可以做到以下:

在程序的运行态可以获取对象所属的类;

在程序的运行态可以构造类的对象实例;

在程序的运行时可以获取,或者修改类的成员属性;

在程序的运行态可以调用某个类,或者对象的方法;

在程序的运行态可以获取类的其他信息,比如描述修饰符、父类信息等;

对文中的"自省"的理解:"自省"应该仅指程序在运行时对自身信息(元数据)的检测,而反射机制不仅仅需要在运行时对程序的自身数据进行检测,还需要根据检测到的数据修改程序的状态或者方法。

用于操作反射的相关的 5 个类:

java.lang.Class:代表类;

java.lang.reflect.Constructor:代表类的构造方法;

java.lang.reflect.Field:代表类的属性;

java.lang.reflect.Method:代表类的方法;

java.lang.reflect.Modifier:代表类、方法、属性的修饰符;

Constructor、Field、Method 这三个类都继承 AccessibleObject,该对象有一个非常重要的方法 AccessibleObject#setAccessible​(boolean flag),这里的所谓 accessible 可以理解成修饰成员的 public、protected、private,这意味着我们可以在程序运行时修改类成员的访问限制。

在类 Object 中有 Object#getClass()、Object#hashCode()、Object#equals(Object obj)、Object#clone()、Object#toString()、Obect#notify()、Object#notifyAll()、Object#wait() 等 public 权限的方法。而 Object#getClass() 方法则是返回程序运行时的 Class 类的对象实例。CLass 类也是同样继承 Object 类,拥有相应的方法。Class 类的类表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,一个注解是一个接口。每个数组还属于一个反映为Class对象的类,该对象由具有相同元素类型和维数的所有数组共享。Java 的基本类型 boolean、byte、char、short、int、long、float、double,和关键字 void 也表示为 Class 对象。

Class 没有 public 类型的构造器。Java 虚拟机会在加载类时以及通过在类加载器中调用 ClassLoader#defineClass() 方法来自动构造 Class 对象。

Modifier 类提供了 static 方法和常量来解码类和成员访问修饰符。修饰符集合被表示为具有不同修饰符的不同位置的整数。表示的范围有 abstract、final、interface、native、private、protected、public、strict、synchronized、transient、volatile。

Constructor

java.lang.reflect.Constructor

Constructor 提供了一个类的单个构造函数的信息和访问。Constructor 允许在将实际参数与 newINstance() 与底层构造函数的形式参数进行匹配时进行扩展转换,如果发生缩小转换,则抛出 IllegalArgumentException。

方法

含义

Constructor>[] getConstructors()

返回包含一个 Constructor 对象的数组,元素表示为所指定的类的所有的 public 权限的构造函数

getDeclaredConstructors()

表示返回包含 Constructor 对象的数组,元素表示为指定类的构造函数,包含非 public 权限的

getConstructor(class>... parameterTypes)

返回一个 Constructor 对象,表示指定参数的类的 public 权限的构造函数

getDeclaredConstructor(class>... parameterTypes)

表示返回一个表示 Constructor 对象,表示指定参数的构造函数,包含非 public 权限的

Field

java.lang.reflect.Field

Field 提供有关类或接口的单个字段的信息和动态访问。 反射的字段可以是类(静态)字段或实例字段。Field 允许在获取或设置访问操作期间扩展转换,但如果发生缩小转换,则抛出 IllegalArgumentException。

方法

含义

getFields()

返回包含一个数组 Field 对象,表示的类或接口的所有可访问的公共字段

getDeclaredFields()

返回包含一个数组 Field 对象,表示的类或接口声明的所有字段

getField(String name)

返回包含一个数组 Field 对象,表示的类或接口指定的可访问的公共字段

getDeclaredField(String name)

返回包含一个数组 Field 对象,表示的类或接口指定的任意权限的公共字段

Method

java.lang.reflect.Method

Method 提供有关类和接口上单一方法的信息和访问权限。 反映的方法可以是类方法或实例方法(包括抽象方法)。

方法

含义

getMethods()

获取类所有的 public 方法

getMethod(String name, class>... parameterTypes)

获取类特定的 public 方法

getDeclaredMethods()

获取类所有的方法

getDeclaredMethod(String name, class>... parameterTypes)

获取类特定的方法

反射机制原理

Java 虚拟机可以通过称为运行时类型信息(RTTI, Run Time Type Information)的技术在运行时检查任何类,这是通过一种称为 Class 对象的特殊对象完成的,该对象包含有关类的信息。

虚拟机为每个类管理一个独一无二的 Class 对象。也就是说,每个类都有一个 Class 对象实例。在运行程序的时候,JVM 首先需要会去检测所需加载的类的 Class 是否已经完成加载。如果没有加载在 JVM 中,那么 JVM 回去寻找对应类名的 .class 文件,完成对 Class 对象的加载。通过 Class 对象,我们可以实例化对应的 Class 类对象,调用其构造器(Constructor)、调用类的成员方法(Method)、访问或者修改类的成员属性(Field)。通过 AccessibleObject#setAccessible​(boolean flag) 可以访问到类的非 public 权限的其他成员,在上文提到通过 AccessibleObject#setAccessible​(boolean flag) 可以在程序运行时修改类成员的访问限制。实际上,AccessibleObject#setAccessible​(boolean flag) 关闭了权限的访问检查,使得通过 Class#invoke() 可以访问到任意权限的类成员。

Java反射实践

Java反射调用内部类

Java 的内部类可分为普通内部类、静态内部类。JVM 在编译含有普通内部类的时候,默认会在构造方法中传入外部类对象的引用,这也是为什么内部类对象会持有外部类的引用。我们可以通过解析 .class 字节码来验证这一推论。

有上面的基础,我们可以推断出,在反射调用普通内部类的成员的时候,我们需要在普通内部类的构造方法中传入外部类的对象引用。而静态内部类由于不持有外部类的引用,因而不需要在其构造方法中传入外部类的引用。

举个例子。有一个类 OutClass,然后 OutClass 含有一个普通内部类 InnerClass、以及静态内部类 StaticClass。我们通过反射分别实例化它们的时候,如下图:

反射调用普通内部类和静态内部类,只是在实例化的构造器的时候有区别,对于调用内部类的 Field、Method、Constructor,其过程是和调用普通类的过程时一样的,在这里就不一一细述了(主要因为我懒)。

小结

Java 的反射机制用起来挺复杂的。但 Java 的反射机制在 Android 组件化中解耦合起到了很大的作用。可以在程序运行时访问类的成员属性或修改属性、执行方法、以及执行构造方法。并且在 Android 的许多源码中,有很多的属性、方法被标记了 @hide,但通过 Java 的反射,仍然可以访问这些属性、方法。

java的自省机制_深入理解Java反射机制相关推荐

  1. java 异常机制_深入理解Java异常处理机制

    一.引子 try-catch-finally恐怕是大家再熟悉不过的语句了,而且感觉用起来也是很简单,逻辑上似乎也是很容易理解.不过,我亲自体验的"教训"告诉我,这个东西可不是想象中 ...

  2. java异常机制_全面理解java异常机制

    在理想状态下,程序会按照我们预想的步骤一步一步的执行,但是即使你是大牛,你也不可避免出错,所以java为我们提供了异常机制.本文将会从以下几个方面介绍java中的异常机制: 异常机制的层次结构 异常的 ...

  3. 深入理解Java虚拟机知乎_深入理解Java虚拟机(类文件结构)

    深入理解Java虚拟机(类文件结构) 欢迎关注微信公众号:BaronTalk,获取更多精彩好文! 之前在阅读 ASM 文档时,对于已编译类的结构.方法描述符.访问标志.ACC_PUBLIC.ACC_P ...

  4. java静态注解处理器_深入理解Java:注解(Annotation)--注解处理器

    如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了.使用注解的过程中,很重要的一部分就是创建于使用注解处理器.Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处 ...

  5. Java虚拟机不能满足_深入理解Java虚拟机--读书笔记1/3

    <深入理解Java虚拟机-JVM高级特性与最佳实践> Chap 2 Java内存区域与内存溢出异常 1.Java运行时数据区域 A.程序计数器:当前线程所执行字节码的行号指示器,线程私有( ...

  6. java调用子系统代码_深入理解JAVA虚拟机-Idea远程执行本地Java代码 - Java 技术驿站-Java 技术驿站...

    今天在看深入理解JAVA虚拟机的9.3节,作者实现了一个远程执行功能.这个功能可以在远程服务器中临时执行一段程序代码,而去不依赖jdk版本,不改变原有服务端程序的部署,不依赖任何第三方库,不入侵原有的 ...

  7. java虚引用作用_深入理解Java中的引用(二)——强软弱虚引用

    深入理解Java中的引用(二)--强软弱虚引用 在上一篇文章中介绍了Java的Reference类,本篇文章介绍他的四个子类:强引用.软引用.弱引用.虚引用. 强引用(StrongReference) ...

  8. java 接口和虚构_深入理解Java的接口和抽象类

    深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...

  9. java虚拟机编译顺序_深入理解Java虚拟机(程序编译与代码优化)

    文章首发于微信公众号:BaronTalk,欢迎关注! 对于性能和效率的追求一直是程序开发中永恒不变的宗旨,除了我们自己在编码过程中要充分考虑代码的性能和效率,虚拟机在编译阶段也会对代码进行优化.本文就 ...

  10. java抽象类的属性_深入理解Java抽象类

    基础部分内容差不多讲解完了,今天开始进入Java提高篇部分,这部分内容会比之前的内容复杂很多,希望大家做好心理准备,看不懂的部分可以多看两遍,仍不理解的部分那一定是我讲的不够生动,记得留言提醒我. 好 ...

最新文章

  1. 烂泥:高负载均衡学习haproxy之TCP应用
  2. 如何解决android 通知栏不显示的问题
  3. jni invalid jobject
  4. Qt控制台输出QString
  5. 基于子类的动态代理:
  6. 前端多图片上传怎么控制顺序_Web前端经典面试题有哪些 如何能走向高薪之路...
  7. MATLAB学习笔记(七)——MATLAB解方程与函数极值
  8. mongoexport导出mongodb数据库中的数据
  9. 【前端周刊】20190606
  10. preHandle、postHandle与afterCompletion
  11. python执行sql语句慢很多_Python学习教程:面试问:一条SQL语句执行得很慢的原因有哪些?...
  12. usb无线网卡linux驱动,Linux系统下安装USB无线网卡驱动方法
  13. oracle优化distinct,oracle中使用group by优化distinct
  14. Eclipse下载以及旧版本下载
  15. 数组输出c语言getchar,C语言入门 — getchar
  16. 商汤科技推出SenseCore AI大装置,打造物理世界的搜索引擎
  17. Spring @Transactional注解出错:CglibAopProxy - Unable to apply any optimisations to advised method
  18. liunx 全盘查找_Linux中查找文件夹的命令
  19. AIX磁盘管理基础知识
  20. 关于北洋壳的网友问题

热门文章

  1. 【Elasticsearch】优秀实践-Elasticsearch查询调优
  2. 在 Vue2 中引入高德地图和三维模型
  3. 计算机病毒论文课题内容,计算机病毒防治学论文选题 计算机病毒防治论文题目怎样定...
  4. kb mac压缩图片大小_mac怎么缩小图片kb
  5. java 网页版通讯_JavaWeb网页聊天室(WebSocket即时通讯)
  6. 一个月的时间让你的词汇量翻一翻
  7. android 飞行模式 配置 wifi可用,飞行模式下使用WiFi教程
  8. UMLChina公众号文章精选(20220821更新精选)
  9. Windows 技术篇 - win10系统更新后切换应用一直自动切换为微软输入法解决方法,win10微软输入法卸载方法
  10. IOS捷径|九宫格切图工具 分享