摘要:本文详细深入讲解是Java中反射的机制,并介绍了如何通过反射来生成对象、调用函数、取得字段、设置字段的方法。最后,给出了一些反射常用到的实例。
一、反射
(1)概念
反射含义:可以获取正在运行的Java对象。
(2)功能
1)在运行时判断任意一个对象所属的类
2)在运行时构造任意一个类的对象
3) 在运行时判断任意一个类所具有的成员变量和方法
4)在运行时调用任意一个对象的方法
(3)实现Java反射的类
1)Class:它表示正在运行的Java应用程序中的类和接口
2)Field:提供有关类或接口的属性信息,以及对它的动态访问权限
3)Constructor:提供关于类的单个构造方法的信息以及对它的访问权限
4)Method:提供关于类或接口中某个方法信息
注意:Class类是Java反射中最重要的一个功能类,所有获取对象的信息(包括:方法/属性/构造方法/访问权限)都需要它来实现
(4)取得class的三种方法
1 | Dog dog = new Dog(); |
(5)关键方法
方法关键字 | 含义 |
getDeclaredMethods() | 获取所有的方法 |
getReturnType() | 获得方法的放回类型 |
getParameterTypes() | 获得方法的传入参数类型 |
getDeclaredMethod(“方法名”,参数类型.class,……) | 获得特定的方法 |
构造方法关键字 | 含义 |
getDeclaredConstructors() | 获取所有的构造方法 |
getDeclaredConstructor(参数类型.class,……) | 获取特定的构造方法 |
父类和父接口 | 含义 |
getSuperclass() | 获取某类的父类 |
getInterfaces() | 获取某类实现的接口 |
(6)一些区别函数
public Method[] getMethods()返回某个类的所有公用(public)方法包括其继承类的公用方法,当然也包括它所实现接口的方法。
public Method[] getDeclaredMethods()对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。当然也包括它所实现接口的方法。
getFields()获得某个类的所有的公共(public)的字段,包括父类。
getDeclaredFields()获得某个类的所有申明的字段,即包括public、private和proteced,
但是不包括父类的申明字段。
下面来看一个例子说明:
动物接口
1 | package com.lin; |
实现类:
1 | package com.lin; |
来看看各自的调用:
1 | package com.lin; |
来看下结果:
getMethods方法
getDeclareMethos方法:
从上面可以看出getMethods()返回某个类的所有公用(public)方法包括其继承类的公用方法,当然也包括它所实现接口的方法。getDeclaredMethods()对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。当然也包括它所实现接口的方法。
二、通过反射调用构造函数
(1)、列出所有的构造函数:
1 | Constructor<?>[] constructors = dogClass.getConstructors(); |
输出结果:
(2)、通过反射生成对象
1 | System.out.println("====================通过newInstance()来生成对象,一定在有默认构造函数===================="); |
输出结果:
从上面可以看出,先通过getConstructor(new Class[]{xxxx.class,yyy.class}),再通过con1.newInstance(new Object[]{“xxxxx”,…});的方式是最灵活的,可以自动根据输入的参数类型和个数,找到对应的构造函数来调用。第二种方法需要得到构造函数的数组,并且需要知道对应哪一个构造函数。第一种就只能调用无参构造函数。
三、通过反射调用普通函数、静态函数
(1)取得函数的一些基本信息
1 | Class<?> dogClass = Dog.class; |
输出结果:
其中函数类型对应表如下:
PUBLIC: 1
PRIVATE: 2
PROTECTED: 4
STATIC: 8
FINAL: 16
SYNCHRONIZED: 32
VOLATILE: 64
TRANSIENT: 128
NATIVE: 256
INTERFACE: 512
ABSTRACT: 1024
STRICT: 2048
(2)方法调用
这是当前狗类的方法:
1 | package com.lin; |
不同方法的调用过程:
1 | //调用私有方法 |
输出结果:
方法调用这里一定要记住getMethod和getDeclaredMethod的区别,并且在调用私有的方法之前一定要加setAccessible(true)这一句,要不会报错!
四、通过反射取得字段、设置字段值
(1)怎么通过反射获取类的属性
a)Class.getDeclaredField(String name);
返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
b)Class.getDeclaredFields();
返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
c)Class.getField(String name);
返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
d)Class.getField();
返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
(2)进行属性获取更改
1 | Dog dog1 = new Dog("狗狗1号", 12); |
输出结果:
值得注意的是获取私有属性的时候必须先设置Accessible为true,然后才能获取。
五、反射常用工具类
(1)bean复制工具
这里可以使用commons-beanutils中的copyProperties()方法,自己写是为了加深对反射的理解。
1、toString的基类
1 | package com.lin; |
2、bean复制工具
1 | package com.lin; |
使用:
新建两个类:
1 | package com.lin; |
另一个:
1 | package com.lin; |
调用:
1 | public static void test5() { |
除了两个不同的字段外,其它的都复制过去了,这在DTO、VO、DOMAIN对象转换时经常用到。
林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka