Java 反射机制

基本概念

Java 运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?

答案是 肯定的。

这种动态获取类的信息以及动态调用对象的方法的功能来自于Java语言的 反射(Reflection)机制

Java反射机制主要提供了以下功能:

1.在运行时判断任意一个对象所属的类。

2.在运行时构造任意一个类的对象。

3.在运行时判断任意一个类所具有的成员变量和方法。

4.在运行时调用任意一个对象的方法。

Reflection是Java被视为动态(或准动态)语言的一个关键性质。

这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息。

包括其modifiers(诸如public、static等)、 superclass(例如Object)、实现了的 interfaces (例如Serializable)、也包括其fields和methods的所有信息,并可于运行时改变fields内容或调用methods。

动态语言

动态语言的定义”程序运行时,允许改变程序结构或者变量类型,这种语言称为动态语言”。

从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。

尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。这个字的意思是: 反射、映像、倒影,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。

换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造( 但不包括 methods 定义),并生成其对象实体、或对其fields设值、或唤起其methods。

这种”看透”class的能力(the ability of the program to examine itself)被称为 introspection(内省、内观、反省)。 Reflectionintrospection是常被并提的两个术语。

Java Reflection API简介

在JDK中,主要由以下类来实现Java反射机制,这些类(除了第一个)都位于 java.lang.reflect包中

Class类:代表一个类,位于java.lang包下。

Field类:代表类的成员变量(成员变量也称为类的属性)。

Method类:代表类的方法。

Constructor类:代表类的构造方法。

Array类:提供了动态创建数组,以及访问数组的元素的静态方法。

Class对象

要想使用反射,首先需要获得待操作的类所对应的Class对象。

Java 中,无论生成某个类的多少个对象,这些对象都会对应于同一个Class 对象。

这个Class 对象是由JVM 生成的,通过它能够获悉整个类的结构。

常用的获取Class 对象的3 种方式:

1.使用Class类的静态方法。例如:

2.使用类的.class语法。如:

3.使用对象的getClass()方法。如:

getClass()方法定义在Object类中,不是静态方法,需要通过对象来调用,并且它声明为final,表明不能被子类所覆写。

直接print所获得的Class对象classType会输出:

class 完整类名

如果调用该Class对象的getName()方法,则输出完整类名,不加class。

例程1:获取方法

例程DumpMethods类演示了Reflection API的基本作用,它读取命令行参数指定的类名,然后打印这个类所具有的方法信息。

例程2:通过反射调用方法

通过反射调用方法。详情见代码及注释:

生成对象

若想通过类的不带参数的构造方法来生成对象,我们有两种方式:

1.先获得Class对象,然后通过该Class对象的newInstance()方法直接生成即可:

2.先获得Class对象,然后通过该对象获得对应的Constructor对象,再通过该Constructor对象的newInstance()方法生成

(其中Customer是一个自定义的类,有一个无参数的构造方法,也有带参数的构造方法):

若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:

(Customer为一个自定义的类,有无参数的构造方法,也有一个带参数的构造方法,传入字符串和整型)

可以看出调用构造方法生成对象的方法和调用一般方法的类似,不同的是从Class对象获取Constructor对象时不需要指定名字,而获取Method对象时需要指定名字。

如下例程ReflectTester类进一步演示了Reflection API的基本使用方法。

ReflectTester类有一个copy(Object object)方法,这个方法能够创建一个和参数object同样类型的对象,然后把object对象中的所有属性拷贝到新建的对象中,并将它返回。

这个例子只能复制简单的类,假定类的每个属性都有public类型的getXXX()和setXXX()方法。

反射与数组

java.lang.Array类提供了动态创建和访问数组元素的各种 静态方法。

多维数组

首先,区别一下下面两者:

输出:

int

class java.lang.Integer

一个多维数组的程序实例:

利用反射调用私有方法、访问私有属性

利用反射,首先是Class对象的获取,之后是Method和Field对象的获取。

以Method为例,从文档中可以看到:

getMethod()方法返回的是public的Method对象,

而getDeclaredMethod()返回的Method对象可以是非public的。

Field的方法同理。

访问私有属性和方法,在使用前要通过AccessibleObject类(Constructor、 Field和Method类的基类)中的setAccessible()方法来抑制Java访问权限的检查

实例1,调用私有方法

假设有这样一个类,其中包含私有方法。

利用反射机制在外部访问该方法

实例2,访问私有属性

直接访问私有属性,将例子中的私有属性改值。

一个包含私有属性的类:

利用反射修改其私有属性的值:

Java中的 Object类,是所有类的继承根源,其中的 getClass()方法返回一个 Class Object。所有的类都有这个方法。

Class类十分特殊,它和其他类一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitive Java types(boolean, byte, char, short, int, long, float, double)以及关键词void。

当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM便自动产生一个Class对象(Class object)。

如果您想借由修改Java标准库源码来观察Class对象的实际生成时机,例如在Class的constructor内添加println(),那是不可以的。因为Class没有public constructor。

Class是Reflection起源。针对任何您想探勘的类,唯有先为它产生一个Class object,接下来才能经由后者唤起为数十多个的Reflection APIs。

“Class”object的取得途径

1.运用getClass()方法,返回Class对象。

运用Class.getSuperclass()可以得到父类的Class对象,如果是Object类则返回null。

2.运用静态方法Class.forName()

3.运用.class语法。类名.class

其中,还可以通过int[].class的形式获得整形数组的Class对象。

包装类的 .TYPE 语法实际返回的是所对应的原生数据类型的Class对象。

Original: https://www.cnblogs.com/doudouxiaoye/p/5819813.html
Author: 肥宅兜
Title: Java 反射机制

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/537495/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Spring Boot:快速入门教程

    什么是Spring Boot? Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进…

    Java 2023年5月30日
    078
  • Linux firewall防火墙设置

    1、查看firewall服务状态 2、查看firewall的状态 3、开启、重启、关闭、firewalld.service服务 4、查看防火墙规则 5、查询、开放、关闭端口 Ori…

    Java 2023年6月7日
    082
  • Lucene、solr以及elasticsearch之间的区别和联系

    微信搜索:小大白日志 Lucene、solr以及elasticsearch之间的区别和联系 lucene,就是一个jar包,里面包含了封装好的各种建立倒排索引、以及进行搜索的代码,…

    Java 2023年6月8日
    084
  • JAVA的类型转换(基本类型)

    类型转换 由于java是强类型语言,所以在进行某些运算的时候,需要用到类型转换。 低–>高指的是字节大小,从小到大。 小数的优先级大于整数 数值进行类型转换时不要…

    Java 2023年6月9日
    084
  • markdown mermaid状态图

    状态图 状态图是一种用于计算机科学和相关领域描述系统行为的图。状态图要求描述的系统由有限数量的状态组成。 语法: stateDiagram-v2 [*] –> Still …

    Java 2023年6月5日
    078
  • java的XML解析(DOM4J技术)

    DOM4J技术解析XML文件 一,XML简介 xml (可扩展标记语言) 全称: Extended Markup Language可扩展的含义:允许程序员按照自己的想法去扩展新的标…

    Java 2023年6月8日
    071
  • Java8-Stream流

    Java8-Stream基础操作 JAVA技术交流群:737698533 在学习Stream之前必须有Lambda,的基础 Stream是Java8的新特性,可以进行对集合进行一些…

    Java 2023年6月6日
    087
  • 在图片上指定区域写文字,超过长度自动换行

    public static void main(String[] args) throws IOException { BufferedImage bufferedImage = …

    Java 2023年6月5日
    069
  • 1.初学 servlet

    创建servlet,除了实现Servlet接口之外,还可以继承 GenericServlet 或 HttpServlet。 继承HttpServlet类创建Servlet pack…

    Java 2023年6月8日
    080
  • 改Bug的经验

    如果修复某个Bug花了很长时间,这时候就要问问自己为什么,怎么做才吸取经验教训,在类似的问题上不再出问题,以及采用的方法,使用的工具是否还有改进的地方;当所有问题都解决之后,一定要…

    Java 2023年6月15日
    060
  • DispatcherServlet 分发流程

    0 太长不看版 HTTPServlet 的 Service 方法将请求按类进行分解 主要是根据HTTP方法的类型调用 doXXX 方法 GET 和 HEAD 方法需要对 if-mo…

    Java 2023年6月9日
    0105
  • 多线程_锁

    介绍锁之前,先介绍一下JUC(java util concurrent)。它是java提供的一个工具包,里面有我们常用的各种锁,它分为3个包 java.util.concurren…

    Java 2023年6月7日
    055
  • Java WebService 简单实例

    前言:朋友们开始以下教程前,请先看第五大点的注意事项,以避免不必要的重复操作。 一、准备工作(以下为本实例使用工具) 1、MyEclipse10.7.1 2、JDK 1.6.0_2…

    Java 2023年5月29日
    0143
  • Swagger详解(SpringBoot+Swagger集成)

    Swagger-API文档接口引擎Swagger是什么Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和…

    Java 2023年5月30日
    096
  • iphone 开发学习笔记六

    结束了选择开发平台的思想斗争,最终选择MonoTouch. 最终的代码需要在iphone上测试,尽管可以使用iphone模拟器来开发,但模拟器和16实际的手机还是有很大的区别的。内…

    Java 2023年5月29日
    082
  • DHCP 动态主机设置协议 分析

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年6月9日
    077
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球