一文带你了解Java反射机制

想要获取更多文章可以访问我的博客?-?代码无止境

上周上班的时候解决一个需求,需要将一批数据导出到Excel。本来公司的中间件组已经封装好了使用POI生成Excel的工具方法,但是无奈产品的需求里面有个合并单元格的要求,工具类中找了半天也没发现适用的方法,就只能自己撸起袖子干了。导出Excel的工具方法会少不了使用反射,但是反射这东西对于我这种写业务代码的人来说接触比较少,所以就恶补了一下,写下这篇文章记录一下。

什么是反射

万物究其根,研究一样新东西,首先我们需要了解它是什么,干什么用的。在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。那么我们又能利用反射做什么呢?

  • 在运行时分析类。
  • 在运行时查看对象,我们还可以利用反射编写一个toString方法供所有类使用。
  • 利用Method对象,在运行时任意调用一个对象的方法。

那么本篇文章将围绕者上面三个点来了解一下Java的反射机制。在开始之前,我们先来介绍一下一个类,这个类是我们在使用反射的过程中必不可少会使用到的一个类。

Class类

在运行时,Java运行时系统会为每一个对象都维护一个标识这个对象类型的信息,而保存这些信息的类型就是Class类。我们可以通过对象的getClass()方法来获取该对象对于的Class对象,就像下面这样。

User user = new User();
Class c = user.getClass();

这个世界上的任何东西都有它存在的意义,那么我们可以用Class对象来干什么呢?我们最常使用Class来判断一个对象是不是属于某个类型,就像下面这样:

User user = new User();

if (user.getClass() == User.class) {
    System.out.println("user is User");
}

当然我们也经常会使用Class类的getName()方法来获取某个类的名称。有写时候,我们还会利用它的newInstance()方法来获取某个类型的实例(当这类没有提供共有的构造方法时)。

利用反射分析类

分析一个类,无外乎就是查看这个类中的属性、方法以及其构造方法了。在Java的反射包中提供了三个类Field、Method以及Constructor来分别描述属性、方法和构造器。
下面我们就分别来看下,我们是如何通过反射机制来获取一个类的这些信息的。
1.获取属性

User user = new User();
Class cl = user.getClass();
Field[] fields1 = cl.getFields();
Field[] fields2 = cl.getDeclaredFields();

可以看到我们可以利用getFields()getDeclaredFields()两个方法来获取类中的属性列表,那么这两个方法有什么区别呢?区别就是前者只会返回类的共有成员信息,而后者这会返回类中所有的成员信息包括公有的、私有的、受保护的,但是不包括父类的成员信息。

2.获取构造器

Constructor[] constructors1 = cl.getConstructors();
Constructor[] constructors2 = cl.getDeclaredConstructors();

3.获取方法

Method[] methods1 = cl.getMethods();
Method[] methods2 = cl.getDeclaredMethods();

可以看到我们可以通过一个类的Class对象很轻松的获取他的属性、构造器以及方法信息。但是在Field、Constructor以及Method中又分别提供了哪些api呢?下面我们就一起来看下。

1.getName()方法,用来获取对应的名称。同时存在于Field、Constructor以及Method类中
2.getModifiers()方法来获取前面的修饰符(public等),但是getModifiers()返回的是一个int值,我们可以通过Modifier.toString(int i)将其转换成对应的字符串。也同样同时存在于Field、Constructor以及Method类中。
3.getParameterTypes()方法,用来获取方法的参数类型数组。存在于Constructor以及Method类中
4.getReturnType()方法,用来获取方法的返回类型。只存在于Method类中

有了这些api,我们就拥有了在运行时分析一个类的能力,我们可以通过一个简单的小例子来实践一下,我们可以编写一个方法来输出一个类的完整信息,具体的实现会在文末给出,大家可以先自己尝试一下。

利用反射查看对象

有些时候呢,我们可能也需要反射去获取对象中属性的值,比如说在导出Excel的时候,我们只知道列所对应属性的字段名称,然后我们需要通过反射获取它的值,然后把它写到Excel中。那么这节内容就一起来看下如何利用Java的反射机制来分析对象。

User user = new User(1,"itweknow");
Class cl = user.getClass();
Field userName = cl.getDeclaredField("userName");
Object value = userName.get(user);

就像上面的代码一样,我们可以使用Field类中提供的get(Object obj)方法来获取属性的值,对于基础类型还提供了特定的get方法,比如getDouble()。但是如果上面的userName是个私有属性的话,get()方法肯定会抛出IllegalAccessException的异常。这是时候我们需要使用setAccessible()方法覆盖安全管理器的访问控制。

User user = new User(1,"itweknow");
Class cl = user.getClass();
Field userName = cl.getDeclaredField("userName");
userName.setAccessible(true);
Object value = userName.get(user);

setAccessible()方法在FieldMethodConstructor类中都有提供。与get()方法呼应,Field还提供了set()方法用来给属性设置值。

利用反射调用任何方法

在Method类中提供了invoke()方法来调用,当前Method对象所包装的方法。invoke()方法的定义如下:

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

第一个参数是调用这个方法的对象,第二个参数是该方法的参数,是一个数组的形式。下面我们就来看下如何利用反射来调用User类中的sayHello()方法吧。

Method sayHelloMethod = cl.getDeclaredMethod("sayHello", String.class);
sayHelloMethod.setAccessible(true);
sayHelloMethod.invoke(user, "Reflect");

看上面的代码我们通过getDeclaredMethod()方法来获取了一个名为sayHello的私有方法(PS:如果是公有方法的话直接使用getMethod()方法就可以了),同样对于私有方法,我们需要修改它的访问控制才能顺利调用。

API整理

上面的章节中提到了不少Java反射机制中提供的Api,下面是我整理的一些常用的反射Api,大家可以参考一下。

1.Class类

Api 描述
forName() 返回指定类名的Class对象
newInstance() 返回一个这个类的新实例
getFields() 返回这个类所有的公有属性
getDeclaredField() 返回这个类所有的属性(包含公有、私有、受保护)
getMethods() 返回这个类下所有的共有方法
getDeclaredMethods() 返回这个类所有的方法(包含公有、私有、受保护)
getConstructors() 返回这个类所有公有的构造器
getDeclaredConstructors() 返回这个类所有的构造器(包含公有、私有、受保护)
getField() & getDeclaredField() 返回这个类中指定名称的属性
getMethod() & getDeclaredMethod() 返回指定名称和参数的方法
cl.getConstructor() & cl.getDeclaredConstructor() 获取指定参数的构造器

2.Field类

Api 描述
getModifiers() 返回一个用于描述属性的修饰符的整型数值。使用 Modifier类中的toString()方法将其转为字符串。
getName() 返冋一个用于描述属性名的字符串。

3.Method类

Api 描述
getModifiers() 返回一个用于描述方法的修饰符的整型数值。使用 Modifier类中的toString()方法将其转为字符串。
getName() 返冋一个用于描述方法名的字符串。
getParameterTypes() 返回一个用于描述参数类型的Class对象数组。
getReturnType() 返回一个用于描述返H类型的Class对象。
invoke() 调用这个对象所描述的方法, 传递给定参数,并返回方法的返回值。

4.Constructor类

Api 描述
getModifiers() 返回一个用于描述构造器的修饰符的整型数值。使用 Modifier类中的toString()方法将其转为字符串。
getName() 返冋一个用于描述构造器名的字符串。
getParameterTypes() 返回一个用于描述参数类型的Class对象数组。

5.AccessibleObject类

Api 描述
setAccessible(boolean flag) 为反射对象设置可访问标志。flag 为 true 表明屏蔽 Java 语言的访问检查,使得对象的私有属性也可以被査询和设置。
isAccessible() 返回反射对象的可访问标志的值。

结束语

这篇文章主要和大家一起了解了一下Java的反射机制,以及在反射包下FieldMethodConstructor三个类所提供的api。在利用反射分析类小节中,我提到了使用反射打印类的完整信息,具体的实现代码点击这里获取。希望这篇文章能够对大家有所帮助。最后,如果你喜欢这篇文章的话欢迎在Github源码项目点个Star。

PS:学习不止,码不停蹄!如果您喜欢我的文章,就关注我吧!

原文地址:https://www.cnblogs.com/endless-code/p/11261558.html

时间: 2024-10-09 22:27:45

一文带你了解Java反射机制的相关文章

Java 反射机制(一)

Java 反射机制 基本概念 在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法? 答案是肯定的. 这种动态获取类的信息以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制. Java反射机制主要提供了以下功能: 1.在运行时判断任意一个对象所属的类. 2.在运行时构造任意一个类的对象. 3.在运行时判断任意一个类所具有的成员变量和方法. 4.在运行时调用任意一个对象的方法. Reflection是Jav

Java反射机制深入研究

ava 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”. 在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的.这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制. Java 反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类. 在运行时构造任意一个类的对象. 在运行时判断任意一个类所具有的成员变量和方法. 在运行时调用任意一个对象的方

Java反射机制的学习

Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调用其方法或修改其域(甚至是本身声明为private的域或方法). 也许你使用Java已经很长时间了,可是几乎不会用到Java反射机制.你会嗤之以鼻地告诉我,Java反射机制没啥用.或许在J2EE.J2SE等平台,Java反射机制没啥用(具体我也不了解,不多做评论),但是在Android应用开发中,该

[转载] Java反射机制的学习

本文转载自: http://www.blogjava.net/zh-weir/archive/2011/03/26/347063.html Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调用其方法或修改其域(甚至是本身声明为private的域或方法). 也许你使用Java已经很长时间了,可是几乎不会用到Java反射机制.你会嗤之以鼻地告诉我,Ja

Java 反射机制

使用 Java 反射机制可以在运行时期检查 Java 类的信息,检查 Java 类的信息往往是你在使用 Java 反射机制的时候所做的第一件事情,通过获取类的信息你可以获取以下相关的内容: Class 对象 类名 修饰符 包信息 父类 实现的接口 构造器 方法 变量 注解 除了上述这些内容,还有很多的信息你可以通过反射机制获得,如果你想要知道全部的信息你可以查看相应的文档 JavaDoc for java.lang.Class 里面有详尽的描述. 在本节中我们会简短的涉及上述所提及的信息,上述的

java反射机制分析

本文转自:http://www.cnblogs.com/gulvzhe/archive/2012/01/27/2330001.html 浅显易懂,值得收藏 Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象, 都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制.反射的概念是由Smith在1982年 首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.这一概念的提出很快引发了

java 反射机制:运行时的类信息(为框架服务的Bug存在)

反射机制:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 换一种引出反射的说法是:当通过反射与一个未知的类型的对象打交道是,JVM只是简单地检查这个类,看它是属于哪个特定的类(就想RTTI那样).在用它做其他事情之前必须先加载那个类的Class对象.因此,那个类的.class文件对于JVM来说必须是可获取的:那么在本地机器上,要么通过网络获得

探索Java反射机制

Java反射机制,可以说我们平常开发中用的很多,尽管作为开发人员,我们并没有什么感觉,那是因为框架的设计者,已经为我们封装好了,我们只需要用去调用一下就可以了.以前也用到过反射,包括自己也写过,也学到过,但是我感觉都比较浅,今天有时间,我觉得有必要去慢慢的深入了解一下. 我们把能够分析类能力的程序称为反射(reflective).反射机制功能及其强大,简单说几个反射的用途: 1.在运行中分析类的能力: 2.在运行中查看对象,例如编写一个通用的tostring方法: 3.实现通用的数组操作代码:

Java 反射机制及Annotation

转自:http://justjavac.iteye.com/blog/714654 Java 反射是 Java 语言的一个很重要的特征. 它允许运行中的 Java 程序对自身进行检查,并能直接操作程序的内部属性.例如,使用 它能获得 Java 类中各成员的名称并显示出来. Java 反射机制主要提供了以下功能: a .在运行时判断任意一个对象所属的类. b .在运行时构造任意一个类的对象. c .在运行时判断任意一个类所具有的成员变量和方法. d .在运行时调用任意一个对象的方法. 在 JDK