Java 反射机制

Java 反射机制,第1张


更多内容,前往IT-BLOG
Java 反射机制,在这里插入图片描述,第2张

反射

Reflection

被视为动态语言的关键,反射机制允许程序在执行期间借助于

Reflection API

取得任何类的内部信息,并能直接 *** 作任意对象的内部属性及方法。反射是一种功能强大且复杂的机制。使用它的主要人员是工具构造者,而不是应用程序员。如果仅对设计应用程序感兴趣,而对构造工具不感兴趣,就没有学习的必要。

一、反射机制提供的功能(什么时候会用到反射)

【1】在运行时判断任意一个对象所属的类。
【2】在运行时构造任意一个类的对象。
【3】在运行时判断任意一个类所具有的成员变量和方法。
【4】在运行时调用任意一个对象的成员变量和方法。
【5】生成动态代理。

二、Class 类

在程序运行期间,

Java

运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。虚拟机利用运行时类型信息选择相应的方法执行。保存这些信息的类被称为

Class

Object

类中的

getClass()

方法将会返回一个

Class

类型的实例。具体细节说明如下:

public class ReflecTest { public static void main(String[] args) throws Exception { // Class 是带泛型的 /* 如果一个 Person 对象表示一个特定的人,那么一个 Class 对象将表示一个特定类的属性。 */ //获取 Class 的方法有三种,第一种如下: Class<Person> clazz = Person.class; //创建 clazz 对应的运行时类 Person 类的对象 //创建类的对象:调用Class对象的newInstance()方法:要求是类必须有一个无参的构造器和类的构造器的访问权限需要足够 Person person = clazz.newInstance(); //也可以先 new 一个对象,通过 getClass 获取 Class对象,从而得知此目标对象的结构 Person personTest = new Person(); //获取 Class 的方法有三种,第二种如下: Class<? extends Person> personTestClass = personTest.getClass(); String clazzName = personTestClass.getName(); //com.reflection.learn.Person System.out.printf(clazzName); //获取 Class 的方法有三种,第三种如下:通过Class 的静态方法获取 Class<?> className = Class.forName("com.reflection.learn.Person"); //通过反射调用运行时类的指定属性 Field name = clazz.getField("name"); //给属性设置set 时,需要将**对象**和值传入 信息定义 public String name; //获取公有方法 name.set(person,"Li Si"); //获取私有方法 private int age; Field age = clazz.getDeclaredField("age"); age.setAccessible(true); age.set(person,20); //通过反射指定运行的方法(无参) Method display = clazz.getMethod("display"); //执行此方法invoke,需要传入对象 display.invoke(person); //如果是静态方法,调用规则如下: //display.invoke(Person.class); //调用有参方法 public void getObject(String name) Method getObject = clazz.getMethod("getObject", String.class); //方法的执行,需传入对象和参数 getObject.invoke(person,"Li Si"); } }

java.lang.Class

:是反射的源头:我们创建一个类,通过编译器

javac.exe

生成对应的

.class

文件。之后使用

java.exe

加载(JVM 的类加载器)此

.class

文件到内存中以后,此文件就是一个运行时类,存在于缓冲区中。这个运行时类本身就是一个

Class

是实例。且一个运行时类只加载一次。

三、通过反射调用类中指定的方法和属性(重要)

@Test public void test2() throws Exception{ //获取指定的构造器 Class<Person> clazz = Person.class; //获取指定构造器 Constructor<Person> declaredConstructor = clazz.getDeclaredConstructor(String.class, int.class); Person person = declaredConstructor.newInstance("li", 20); //输出:Person{name='li', age=20} System.out.println(person.toString()); //获取指定的方法 Method getObject = clazz.getDeclaredMethod("getObject", String.class); getObject.invoke(person,"zhangsan"); }

四、利用反射分析类的能力

java.lang.reflect

包中有三个类

Field

(域)、

Method

(方法)、

Constructor

(构造器)。这三个类都有一个叫做

getName

方法,用来返回项目的名称。

Filed

类有一个

getType

方法,用来返回描述域所属类型的 Class 对象。Method 与 Constructor 类有能够报告参数的方法

getParameterTypes

Method

类还有一个可以报告返回类型的方法

getReturnType()

。这三个类还有一个

getModifiers

方法,返回一个整数值,用不同的位开关描述

public

private

等修饰符。可以通过

Modifier

类的静态方法将整数转化为

public

等。

Class

类的

getDeclareFields

getDeclareMethods

getDeclaredConstructors

方法将分别返回类中声明的全部域、方法和构造器,其中包括私有和受保护的成员,但不包括父类成员。

get

方法有一个需要解决的问题,

name

域是一个

String

时,我们将它当做

Object

返回没有什么问题。但是假定我们想要查看

salary

域。它属于

double

类型,而

java

中数据值类型不是对象。可以使用

Field

类中的

getDouble

方法,也可以调用

get

方法,此时,反射机制将自动地将这个域值打包到相应的对象包装器中,这里打包成

Double

五、应用

【1】JDK 的动态代理:链接
【2】Spring 的 AOP 面向切面编程:链接

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/13518804.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2024-03-08
下一篇 2024-03-10

发表评论

登录后才能评论

评论列表(0条)

保存