Java反射原理如何应用于实际编程场景?

摘要:背景 反射在Java中非常重要,是Java区别于其他编程语言的一大特性。Java中的AOP切面、动态代理等看起来像黑魔法一样的技术,就离不开反射、字节码等。这些技术能在不侵入原有代码的情况下,做一些增强的非功能性需求。多提一句,千万不要把业
背景 反射在Java中非常重要,是Java区别于其他编程语言的一大特性。Java中的AOP切面、动态代理等看起来像黑魔法一样的技术,就离不开反射、字节码等。这些技术能在不侵入原有代码的情况下,做一些增强的非功能性需求。多提一句,千万不要把业务逻辑放在AOP切面、动态代理里,否则后人绝对会骂。 AOP切面:在方法执行前后增加逻辑,可决定方法如何执行、甚至不执行。 动态代理:在运行时生成目标类的代理类,可增强目标类的功能。 本文总结一下反射的原理和实际用法。后续有空再介绍AOP切面、动态代理。 什么是反射? 看一下官方的原文定义: Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members and display them. 翻译过来就是:反射是指一个运行中的Java程序可以检查、修改自己内部的属性,也可称之为自省。反射是Java有别于其它编程语言的一大特性。 从reflection的字面意思看,就是倒影、反射,就好比你照镜子,通过倒影就能知道自己长什么样,理一理头发就能改变发型。 反射的原理 一句话概况就是:JVM会动态加载Class,一个Class实例包含了该类的所有完整信息,如:包名、类名、各个字段、各个方法、父类、实现的接口等。 因此,如果获取了某个类或对象的Class实例,就可以通过它获取到对应类的所有信息。 动态加载是指,JVM在第一次读取到一种Class类型时,才将其加载进内存,而不是一启动就加载所有类的信息。 每加载一种类,JVM就为其创建一个Class类型的实例,并关联起来。也即一个类的不同对象实例,背后对应的是同一个Class实例。 详细介绍可参考:https://www.liaoxuefeng.com/wiki/1252599548343744/1264799402020448 怎么使用反射? 需要熟练使用反射中常见的几个类:Class、Field、Method、Constructor。其它还有参数Parameter类等。可以这么理解,凡是Java对象中出现的东西都能在java.reflect包中找到对应的类。 Class 通过3种方式获取: 类.class:类的class静态变量 对象.getClass() Class.forName("类的全路径名") Field Class实例.getField(name):根据字段名获取某个public的Field(包括父类) Class实例.getDeclaredField(name):根据字段名获取该类声明的某个Field(不包括父类)。常用 Field[] getFields():获取所有的public字段,包括父类的字段。不常用,因为按照Java规范,一般都会定义private字段,然后通过public的getter、setter方法来获取字段值 Field[] getDeclaredFields():获取该类声明所有的字段,不包括父类的字段。常用。 Method Class实例.getMethod(name, Class...):获取某个public的Method(包括父类) Class实例.getDeclaredMethod(name, Class...):获取该类的某个Method(不包括父类) Method[] getMethods():获取所有public的Method(包括父类)。
阅读全文