反射
1. 认识反射机制
什么是java的反射机制呢?众所周知,java的特征之一也是java最大特征是它的重用性。而反射机制就是java重用性的核心。反射机制主要体现的是一个“正”和“反”的不同。所谓正操作就是指在使用一个类时,一定要先导入程序的包,而后根据类进行对象的实例化,通俗来说也就是使用new来实例化对象。而所谓反操作是指可以根据实例化对象反推出其类型,即其所在的类。
2. Class 类对象实例化
java.lang.Class类时反射机制操作的起源,为了适应不同情况下的反射机制操作,Java提供了三种Class类对象实例化的方法:
- 利用Object类中提供的getClass()方法获取实例化对象
eg:Object.getClass() Object类是所有类的父类,所以所有类的实例化对象都可以使用getClass()方法获取Class实例化对象 - 使用“类.class”形式获取指定类或接口的Class实例化对象
- 使用Class类内部提供的forName()方法根据类的完整名称获取实例化对象
3. 反射机制与对象化实例
获得了Class类的实例化对象之后,我们希望的是通过这个对象实例来创建这个 类的更多实例化对象,这就产生了下面的实例化对象的方法
class.getDeclaredConstructor().newInstance()
這個方法的作用就是用.getDeclaredConstructor().newInstance()来代替new操作完成对象的初始化
4. 反射机制与类操作
Java反射机制可以在程序运行状态下,自动获取并调用任意一个类中的组成结构(成员属性、方法等),这样的做法可以避免单一的程序调用模式,使代码开发变得更加灵活。
4.1 反射调用类结构信息
程序开发中,任意定义的类都存在继承关系,同时为了保持代码结构的清晰,也可以利用包来保存不同功能的类,方法如下:
方法 | 类型 | 描述 |
---|---|---|
public Package getPackage() | 普通 | 获取包信息 |
public Class<? super T> getSuperclass() | 普通 | 获取继承父类 |
public Class<?>[] getInterfaces() | 普通 | 获取实现接口 |
这些方法表明当获取了一个类的Class对象之后就意味着这个对象可以获取类之中的一切继承结构信息
4.2 反射调用构造方法
构造方法是类的重要组成部分,也是实例化对象时必须调用的方法,在Class类中可以通过如下表所示的方法获取构造函数
class类获取构造方法:
方法 | 类型 | 描述 |
---|---|---|
public Constructor<?>[] getDeclaredConstructors() throws SecurityException | 普通 | 获取所有的构造方法 |
public Constructor getDeclaredConstructors(Class<?>…parameterTypes) | 普通 | 获取指定参数类型的构造方法 |
public Constructor<?>[] getConstructors() | 普通 | 获取所有public权限的构造方法 |
public Constructor getConstructors(Class<?>…parameterTypes) | 普通 | 获取指定参数类型public权限的构造方法 |
根据上表方法命名的规律可以看出,有Declared就是代表所有的方法,没有的就是权限public的方法,有s的就是获取多个方法,需要用数组来存,没有s的就是获取单个方法。
Constructor类常用方法:
方法 | 类型 | 描述 |
---|---|---|
public T newInstance(Object…initargs) | 普通 | 调用构造方法传入指定参数进行对象实例化 |
public String getName() | 普通 | 获取构造方法名称 |
public Type[] getGenericParameterTypes() | 普通 | 获取构造方法的参数类型 |
public Type[] getGenericExceptionTypes() | 普通 | 获取构造方法抛出的异常类型 |
public int getParameterCount() | 普通 | 获取构造方法的参数个数 |
public T getAnnotation(Class annotationClass) | 普通 | 获取全部申明的Annotation |
public void setAccessible(boolean flag) | 普通 | 设置 构造方法可见性 |
上表中的很多方法其实在反射调用方法中也是可以使用的,这些方法大多都是通用的。
4.3 反射调用方法
每个类都有不同的功能,而这些功能都定义在这些类的方法中。下表是反射的方法调用。
Class获取方法信息的方法
方法 | 类型 | 描述 |
---|---|---|
public Method[] getDeclaredMethods() throws SecurityException | 普通 | 获取类中所有的方法 |
public Method getDeclaredMethod(Class<?>…parameterTypes) | 普通 | 获取指定参数类型的方法 |
public Method[] getMethods() | 普通 | 获取所有public权限的方法 |
public Method getMethod(Class<?>…parameterTypes) | 普通 | 获取指定参数类型public权限的方法 |
Method类常见方法
方法 | 类型 | 描述 |
---|---|---|
public Object invoke(Object obj,Object… args) | 普通 | 方法调用,等价于“实例化对象.方法()” |
public Class<?>getReturnType() | 普通 | 获取方法的返回值类型 |
public int getModifiers() | 普通 | 获取方法修饰符 |
public String getName() | 普通 | 获取构造方法名称 |
public Type[] getGenericParameterTypes() | 普通 | 获取构造方法的参数类型 |
public Type[] getGenericExceptionTypes() | 普通 | 获取构造方法抛出的异常类型 |
public int getParameterCount() | 普通 | 获取构造方法的参数个数 |
public T getAnnotation(Class annotationClass) | 普通 | 获取全部申明的Annotation |
public void setAccessible(boolean flag) | 普通 | 设置 构造方法可见性 |
4.4 反射调用成员属性
Class获取成员属性操作的方法
方法 | 类型 | 描述 |
---|---|---|
public Field[] getDeclaredFields() throws SecurityException | 普通 | 获取本类中所有的成员属性,不去父类和抽象类的 |
public Field getDeclaredField(String name) | 普通 | 获取本类中指定成员属性信息 |
public Field[] getFields() | 普通 | 获取父类中所有public成员信息 |
public Field getField(Class<?>…parameterTypes) | 普通 | 获取父类中定义的全部public成员信息 |
Filed类常见方法
方法 | 类型 | 描述 |
---|---|---|
public Class<?>getType() | 普通 | 获取成员属性类型 |
public void set(Object obj, Object value) | 普通 | 设置成员属性内容 |
public void get(Object obj, Object value) | 普通 | 获取成员属性内容 |
public int getModifiers() | 普通 | 获取成员属性修饰符 |
public void setAccessible(boolean flag) | 普通 | 设置 构造方法可见性 |
4.5 Unsafe工具类
为了进一步扩展反射操作的支持,在Java中还提供了Unsafe类,其最大特点就是绕或JVM的相关对象的管理机制,利用反射来获取对象,这里就不展开说了。
总结
在目前我掌握的反射中,获取Class实例化对象和反射创建类的实例化对象时必须的两步,有了Class类的实例化对象才能反射创建类的实例化对象,然后对方法的调用都是基于对Class类的实例化对象做的,然后将再方法.invoke(Object obj) 运行方法,相当于对象.方法().
关于写博客也有一些自己的想法。刚才在写这片博客时就在想,这样参考书中内容写博客有什么收获吗?想了想感觉这样的模式不行,需要些改变。我认为在有书的情况下,记录书中内容是没什么用处的,“输入等于输出”指的不是讲书中内容搬下来就可以变成自己的了,应该是将自己在看书过程中的思考、发现的问题记录下来才是输入等于输出。光是把书中内容搬下来知识会有一个回顾的效果,而在有书的情况下回顾知识最快捷最有效的绝对不是写一篇博客将书中内容搬下来,应该是认真在看一遍书,回顾一下书中知识。所以我觉得我后面的博客方式会发生写改变,我更希望把在看书途中遇到的难以理解的知识点记下来,把遇到的坑记下来。