说到反射,相信有过编程经验的人都不会陌生。反射机制让Java变得更加的灵活。反射机制在Java的众多特性中是非常重要的一个。下面就让我们一点一点了解它是怎么一回事。
什么是反射
在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射有什么用
1,在运行时判断任意一个对象所属的类;
2,在运行时构造任意一个类的对象;
3,在运行时判断任意一个类所具有的成员变量和方法;
4,在运行时调用任意一个对象的方法;
5,生成动态代理。
反射的API
学习一门语言,一种比较好的方式就是看它的API文档,因为它的API是最权威的,最准确的。下面我们一起看看JDK的API对于反射是如何描述的吧!
与反射有关的所有接口以及类都在java.lang.reflect包里。
接口
接口摘要 | |
| 表示目前正在此 VM 中运行的程序的一个已注释元素。 |
| GenericArrayType 表示一种数组类型,其组件类型为参数化类型或类型变量。 |
| 声明类型变量的所有实体的公共接口。 |
| InvocationHandler 是代理实例的调用处理程序 实现的接口。 |
| 成员是一种接口,反映有关单个成员(字段或方法)或构造方法的标识信息。 |
| ParameterizedType 表示参数化类型,如 Collection<String>。 |
| Type 是 Java 编程语言中所有类型的公共高级接口。 |
| TypeVariable 是各种类型变量的公共高级接口。 |
| WildcardType 表示一个通配符类型表达式,如 ?、? extends Number 或 ? super Integer。 |
类
类摘要 | |
| AccessibleObject 类是 Field、Method 和 Constructor 对象的基类。 |
| Array 类提供了动态创建和访问 Java 数组的方法。 |
| Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。 |
| Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。 |
| Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。 |
| Modifier 类提供了 static 方法和常量,对类和成员访问修饰符进行解码。 |
| Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。 |
| 反射操作的 Permission 类。 |
下面给大家写了一个小实例:
- package reflection;
- public class UserInfo {
- private Integer id;
- private String userName;
- private String password;
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- @Override
- public String toString(){
- return this.getClass().getName();
- }
- }
- package reflection;
- public class GetClass {
- public boolean ClassCheck(){
- try {
- System.out.println("第一种,通过类本身获得对象");
- Class UserClass = this.getClass();
- System.out.println("第一种方式成功!类名:"+UserClass.toString()+"\n");
- System.out.println("第二种,通过子类实例获取父类");
- UserInfo ui = new UserInfo();
- UserClass = ui.getClass();
- Class SubUserClass = UserClass.getSuperclass();
- System.out.println("第二种方式成功!类名:"+SubUserClass.toString()+"\n");
- System.out.println("第三种,通过类名加.class获得对象");
- Class ForClass = reflection.UserInfo.class;
- System.out.println("第三种方式成功!类名:"+ForClass.toString()+"\n");
- System.out.println("第四种,通过类名的字符串获得对象");
- Class ForName = Class.forName("reflection.UserInfo");
- System.out.println("第四种方式成功!类名:"+ForName.toString()+"\n");
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
- @Override
- public String toString(){
- return this.getClass().getName();
- }
- public static void main(String[] args) {
- GetClass gc = new GetClass();
- gc.ClassCheck();
- if (gc.ClassCheck()) {
- System.out.println("所有反射全部成功!");
- }
- else {
- System.out.println("反射有问题,请检查!");
- }
- }
- }
上面四种方法里面,我用的最多的是第四种,这种一般都是配合配置文件一起用的。反射与配置文件的结合让我们的代码变得非常的灵活,易扩展、以维护。可谓是好处多多呀,所以才有那句”反射反射,程序员的快乐!“一起尽情的快乐吧!
- package reflection.getclassname;
- //获得完整的类名
- public class GetClassName {
- public String getNameByClass() {
- String name = "";
- System.out.println("通过类本身获得对象");
- Class UserClass = this.getClass();
- System.out.println("获得对象成功!\n");
- System.out.println("通过类对象获得类名");
- name = UserClass.getName();
- System.out.println("获得类名成功!");
- return name;
- }
- public static void main(String[] args) {
- GetClassName gcn = new GetClassName();
- System.out.println("类名为:"+gcn.getNameByClass());
- }
- }
通过类本身获得对象 获得对象成功! 通过类对象获得类名 获得类名成功! 类名为:reflection.getclassname.GetClass Name |
实例二:获得类的属性
- package reflection.getfields;
- import java.lang.reflect.Field;
- //获得类的属性
- public class GetFields {
- public static void getFieldNames(String className) {
- try {
- //获得类名
- Class c = Class.forName(className);
- //获得所有属性
- Field[] fds = c.getFields();
- for (int i=0; i<fds.length; i++)
- {
- String fn = fds[i].getName();
- Class tc = fds[i].getType();
- String ft = tc.getName();
- System.out.println("该属性的名字为:"+fn+",该属性的类型为:"+ft);
- }
- }catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- GetFields.getFieldNames("reflection.getfields.FieldInfo");
- }
- }
运行结果:
该属性的名字为:id,该属性的类型为:java.lang.String 该属性的名字为:username,该属性的类型为:java.lang.String |
实例三:获得类实现的接口
- package reflection.getinterfaces;
- //获得类实现的接口
- public class GetInterfaces {
- public static void getInterfaces(String className) {
- try {
- //取得类
- Class cl = Class.forName(className);
- Class[] ifs = cl.getInterfaces();
- for (int i = 0; i<ifs.length;i++)
- {
- String IName = ifs[i].getName();
- System.out.println("该类实现的接口名字为:"+IName);
- }
- }catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- GetInterfaces.getInterfaces("reflection.getinterfaces.Student");
- }
- }
该类实现的接口名字为:reflection.getinterfaces.Person |
实例四:获得类及其属性的修饰符
- package reflection.getmodifiers;
- import java.lang.reflect.Field;
- import java.lang.reflect.Modifier;
- import reflection.UserInfo;
- //获得类及其属性的修饰符
- public class GetModifiers {
- private String username = "liu shui jing";
- float f = Float.parseFloat("1.000");
- public static final int i = 37;
- //获得类的修饰符
- public static String useModifiers(UserInfo ui) {
- Class uiClass = ui.getClass();
- int m = uiClass.getModifiers();
- return Modifier.toString(m);
- }
- //获得本类属性的修饰符
- public void checkThisClassModifiers() {
- Class tc = this.getClass();
- Field fl[] = tc.getDeclaredFields();
- for(int i=0;i<fl.length;i++)
- {
- System.out.println("第"+(i+1)+"个属性的修饰符为:"+Modifier.toString(fl[i].getModifiers()));
- }
- }
- public static void main(String[] args) {
- //获得类的修饰符
- UserInfo ui =new UserInfo();
- System.out.println("获得这个类的修饰符:"+GetModifiers.useModifiers(ui)+"\n");
- //获得本类属性的修饰符
- GetModifiers gm = new GetModifiers();
- gm.checkThisClassModifiers();
- }
- }
获得这个类的修饰符:public
第1个属性的修饰符为:private 第2个属性的修饰符为: 第3个属性的修饰符为:public static final |
实例五:获得类的构造函数
- package reflection.getconstructor;
- import java.lang.reflect.Constructor;
- //获得类的构造函数
- public class GetConstructor {
- //构造函数一
- GetConstructor(int a) {
- }
- //构造函数二
- GetConstructor(int a, String b) {
- }
- public static void getConstructorInfo(String className) {
- try {
- //获得类的对象
- Class cl =Class.forName(className);
- System.out.println("获得类"+className+"所有的构造函数");
- Constructor ctorlist[] = cl.getDeclaredConstructors();
- System.out.println("遍历构造函数\n");
- for(int i =0 ; i<ctorlist.length; i++)
- {
- Constructor con = ctorlist[i];
- System.out.println("这个构造函数的名字为:"+con.getName());
- System.out.println("通过构造函数获得这个类的名字为:"+con.getDeclaringClass());
- Class cp[] = con.getParameterTypes();
- for (int j=0; j<cp.length; j++)
- {
- System.out.println("参数 "+j+" 为 "+cp[j]+"\n");
- }
- }
- }catch (Exception e) {
- System.err.println(e);
- }
- }
- public static void main(String[] args) {
- GetConstructor.getConstructorInfo("reflection.getconstructor.GetConstructor");
- }
- }
获得类reflection.getconstructor.GetConstructor所有的构造函数 遍历构造函数
这个构造函数的名字为:reflection.getconstructor.GetConstructor 通过构造函数获得这个类的名字为:class reflection.getconstructor.GetConstructor 参数 0 为 int
这个构造函数的名字为:reflection.getconstructor.GetConstructor 通过构造函数获得这个类的名字为:class reflection.getconstructor.GetConstructor 参数 0 为 int
参数 1 为 class java.lang.String |
实例六:获得父类
- package reflection.getparentclass;
- //获得父类
- public class GetParentClass {
- public static String getParentClass(UserInfoMore uim) {
- //获得父类
- Class uimc = uim.getClass().getSuperclass();
- System.out.println("获得父类的名字为:"+uimc.getName());
- return uimc.getName();
- }
- public static void searchParentClass() {
- }
- public static void main(String[] args) {
- UserInfoMore uim = new UserInfoMore();
- System.out.println("成功获得UserInfoMore的父类:"+GetParentClass.getParentClass(uim));
- }
- }
获得父类的名字为:reflection.UserInfo 成功获得UserInfoMore的父类:reflection.UserInfo |
实例七:获得类的方法
- package reflection.getmethod;
- import java.lang.reflect.Method;
- //获得类的方法
- public class GetMethod {
- public static void getMethods(String className) {
- try {
- System.out.println("开始遍历类"+className+".class");
- //获得类名
- Class cls = Class.forName(className);
- //利用方法获得所有该类的方法
- System.out.println("利用类的getDeclaredMethods获得类的所有方法");
- Method ml[] =cls.getDeclaredMethods();
- System.out.println("遍历获得的方法数组\n");
- for (int i = 0 ;i<ml.length;i++)
- {
- System.out.println("开始遍历第"+(i+1)+"个方法");
- Method m = ml[i];
- System.out.println("开始获取方法的变量类型");
- Class ptype[] = m.getParameterTypes();
- for (int j=0; j<ptype.length; j++)
- {
- System.out.println("方法参数"+j+"类型为"+ptype[j]);
- }
- Class gEx[] = m.getExceptionTypes();
- for (int j=0 ; j<gEx.length; j++)
- {
- System.out.println("异常"+j+"为"+ gEx[j]);
- }
- System.out.println("该方法的返回值类型为:"+m.getReturnType()+"\n");
- }
- }catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- GetMethod.getMethods("reflection.UserInfo");
- }
- }
开始遍历类reflection.UserInfo.class 利用类的getDeclaredMethods获得类的所有方法 遍历获得的方法数组
开始遍历第1个方法 开始获取方法的变量类型 该方法的返回值类型为:class java.lang.String
开始遍历第2个方法 开始获取方法的变量类型 该方法的返回值类型为:class java.lang.Integer
开始遍历第3个方法 开始获取方法的变量类型 方法参数0类型为class java.lang.String 该方法的返回值类型为:void
开始遍历第4个方法 开始获取方法的变量类型 该方法的返回值类型为:class java.lang.String
开始遍历第5个方法 开始获取方法的变量类型 方法参数0类型为class java.lang.Integer 该方法的返回值类型为:void
开始遍历第6个方法 开始获取方法的变量类型 该方法的返回值类型为:class java.lang.String
开始遍历第7个方法 开始获取方法的变量类型 方法参数0类型为class java.lang.String 该方法的返回值类型为:void
|
这次实例不少吧,而且这些小例子都比较简单,相信大家都可以轻松秒懂。上面一些例子的代码并不是完整的,有些只有一些关键代码,如果想要完整的代码请戳下面的链接。最后祝大家学习愉快!
转自