1. 前言
Java反射也是日常开发和阅读源码中经常遇到的, 掌握反射是非常有必要的.
2. 概述
2.1 什么是反射
简单来说, 反射可以帮助我们在动态运行的时候, 对于任意一个类, 可以获得其所有的方法(包括 public protected private 默认状态的), 所有的变量(包括 public protected private 默认状态的).
反射就是把Java类中的各种成分映射成一个个的Java对象.
例如: 一个类有: 成员变量, 方法, 构造方法, 包等等信息, 利用反射技术可以对一个类进行解剖, 把个个组成部分映射成一个个对象.
如图是类的正常加载过程: 反射的原理在于Class对象.
2.2 反射有什么用
a. 获取某些类的一些变量, 调用某些类的私有方法
b. 增加代码的灵活性. 很多主流框架都使用了反射技术.
3. 反射的使用
假如有这样一个类 Person, 它拥有多个成员变量, country,city,name,province,height,age 等, 同时它拥有多个 构造方法, 多个方法, 这些变量, 方法的访问权限既有 public 也有 private 的. 下面我们以这个为例子, 一起看怎样使用反射获得相应的 Filed, Constructor, Method.
1 | import java.lang.reflect.Method; |
3.1 获得构造方法
几个重要的方法
方法 | 描述 |
---|---|
public Constructor getConstructor(Class… parameterTypes) | 获得指定的构造方法,注意只能获得 public 权限的构造方法,其他访问权限的获取不到 |
public Constructor getDeclaredConstructor(Class… parameterTypes) | 获得指定的构造方法,注意可以获取到任何访问权限的构造方法。 |
public Constructor[] getConstructors() throws SecurityException | 获得所有 public 访问权限的构造方法 |
public Constructor[] getDeclaredConstructors() throws SecurityException | 获得所有的构造方法,包括(public, private,protected,默认权限的) |
3.1.1 获得所有的构造方法
1 | import java.lang.reflect.Constructor; |
运行结果:
1 | public Person(java.lang.String,java.lang.Integer) |
3.1.2 获得指定的构造方法
1 | import java.lang.reflect.Constructor; |
运行结果:
1 | public Person(java.lang.String,java.lang.Integer) |
这说明我们成功通过反射调用 Person 带两个参数的沟改造方法.
3.1.3 注意事项
如果该方法, 或者该变量不是 public 访问权限的, 我们应该调用相应的 setAccessible(true) 方法, 才能访问得到
1 | //if Constructor is not public,you should call this |
3.2 获得Filed变量
3.2.1 获得所有的Filed变量
1 | import java.lang.reflect.Field; |
运行结果:
1 | public java.lang.String Person.country |
3.2.2 获得指定的Filed变量
现在假如我们要获得 Person 中的私有变量 age , 我们可以通过以下的代码获得.
1 | import java.lang.reflect.Field; |
运行结果:
1 | integer = 12 |
3.3 执行Method
主要有以下几个方法:
1 | public Method[] getDeclaredMethods() |
3.3.1 获取所有的Method
1 | import java.lang.reflect.Method; |
运行结果:
1 | public java.lang.String Person.toString() |
3.3.2 获取指定的Method
1 | import java.lang.reflect.Method; |
运行结果:
1 | country : CHINA |
3.4 操作数组
1 | import java.lang.reflect.Array; |
运行结果:
1 | ----> object=帅哥,className=java.lang.String |
从结果可以说明, 我们成功通过 Array.set(strArray,0,”帅哥”) 改变数组的值.
3.5 获得泛型类型
1 | public static void getGenericHelper(HashMap<String, Person> map) { |
现在假设我们有这样一个方法, 那我们要怎样获得 HashMap 里面的 String, Person 的类型呢?
1 | import java.lang.reflect.Method; |
运行结果:
1 | ----> rawType=class java.util.HashMap |
3.6 怎样获得Metho, Field, Constructor的访问权限(public, private, ptotected等)
其实很简单, 我们阅读文档可以发现他们都有 getModifiers() 方法, 该方法放回 int 数字, 我们在利用 Modifier.toString() 就可以得到他们的访问权限.
1 | int modifiers = method.getModifiers(); |