认识Java 的反射机制

简介: 反射Reflection被视为动态语言的关键,反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。反射是一种功能强大且复杂的机制。使用它的主要人员是工具构造者,而不是应用程序员。

反射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月前
|
网络协议 算法 Java
|
1月前
|
开发框架 Java API
java反射机制的原理与简单使用
java反射机制的原理与简单使用
17 1
|
21小时前
|
设计模式 Java Spring
来聊聊Java的反射机制(下)
来聊聊Java的反射机制(下)
5 0
|
2天前
|
Java 数据库连接
深入理解Java异常处理机制
【4月更文挑战第24天】本文将探讨Java中的异常处理机制,包括异常的概念、分类、捕获和抛出等方面。通过深入了解异常处理机制,可以帮助我们编写更加健壮的程序,提高代码的可读性和可维护性。
|
3天前
|
Java
Java 反射
Java 反射
|
3天前
|
设计模式 Java 索引
由反射引出的Java动态代理与静态代理
由反射引出的Java动态代理与静态代理
12 0
|
3天前
|
存储 Java Shell
深入剖析Java中的反射,由浅入深,层层剥离!
深入剖析Java中的反射,由浅入深,层层剥离!
10 1
|
8天前
|
监控 Java 开发者
掌握 Java 反射和动态代理
【4月更文挑战第19天】Java反射和动态代理提供强大功能和灵活性。反射允许运行时检查和操作类,获取类信息、动态调用方法,但可能带来性能损失和降低代码可读性。动态代理则用于创建代理对象,实现透明性和横切关注点分离,常用于日志、权限检查等。两者结合能实现更复杂功能。掌握这些技术能提升代码的灵活性和可扩展性,但也需注意性能和可读性。通过学习和实践,能更好地构建高效软件系统。
|
15天前
|
Java
代码的魔法师:Java反射工厂模式详解
代码的魔法师:Java反射工厂模式详解
26 0
|
18天前
|
安全 Java
java反射篇
java反射篇