一 反射机制概念简介
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。(PS:百度百科)
举个简单例子就是:正常情况下,对于一个存在的类我们可以通过类来创建对象,然后调用其中的属性或方法;但是要是想要通过一个对象来找到对应的类的名称,属性或者方法,这时候就需要用到反射机制了。
如果想要简单了解反射操作,则首先应该认识的是Class类
二 认识Class类
(1)所有类的对象实际上都是Class类的实例
在Java中,Object类是一切类的父类,那么所有类的对象实际上也就都是java.lang.Class类的实例,因此所有对象都可以转变成java.lang.Class类型表示。
(2)一个简单实例,获取完整的类名路径
1
2
3
4
5
6
7
8
9
|
package
javase.reflex;
public
class
GetClassDemo01 {
public
static
void
main(String[] args) {
GetClassDemo01 demo01 =
new
GetClassDemo01();
System.out.println(demo01.getClass().getName());
// 输出:javase.reflex.GetClassDemo01
}
}
|
(3)实例化Class类的三种方式
由于在Class类中并没有定义任何的构造方法,因此一般通过forName(“”)静态方法来实例化对象。当然也可以使用“对象.getClass()”或“类.class”来实例化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package
javase.reflex;
/**
* 实例化Class对象
* */
public
class
GetClassDemo02 {
public
static
void
main(String[] args) {
Class<?> class1 =
null
;
Class<?> class2 =
null
;
Class<?> class3 =
null
;
// 实例化方法一(常用)
try
{
class1 = Class.forName(
"javase.reflex.GetClassDemo02"
);
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
// 实例化方法二
class2 =
new
GetClassDemo02().getClass();
// 实例化方法三
class3 = GetClassDemo02.
class
;
System.out.println(
"类名称:"
+ class1.getName());
System.out.println(
"类名称:"
+ class2.getName());
System.out.println(
"类名称:"
+ class3.getName());
}
}
|
输出:
1
2
3
|
类名称:javase.reflex.GetClassDemo02
类名称:javase.reflex.GetClassDemo02
类名称:javase.reflex.GetClassDemo02
|
三 Class类初体验——通过newInstance()方法实例化对象
方法:public Object newInstance() throws InstantiationException,IllegalAccessException
描述:创建此Class对象所表示的类的一个新实例
(1)通过无参构造方法实例化对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package
javase.reflex;
class
WebSite {
private
String name;
private
String domain;
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
String getDomain() {
return
domain;
}
public
void
setDomain(String domain) {
this
.domain = domain;
}
public
String toString() {
return
"名称:"
+ name +
"\n域名:"
+ domain;
}
}
public
class
InstanceDemo01 {
public
static
void
main(String[] args) {
try
{
Class<?> class1 = Class.forName(
"javase.reflex.WebSite"
);
WebSite webSite = (WebSite) class1.newInstance();
// 实例化WebSite对象
webSite.setName(
"zifangsky的个人博客"
);
webSite.setDomain(
"http://www.zifangsky.cn"
);
System.out.println(webSite);
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
catch
(InstantiationException e) {
e.printStackTrace();
}
catch
(IllegalAccessException e) {
e.printStackTrace();
}
}
}
|
输出:
1
2
|
名称:zifangsky的个人博客
域名:http:
//www.zifangsky.cn
|
需要注意的是,这种实例化方式需要被实例化的对象的类中必须得存在无参的构造方法,不然程序会报错。比如说这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
package
javase.reflex;
class
WebSite02 {
private
String name;
private
String domain;
/**
* 没有无参数构造方法,下面在进行实例化时会报错
* */
// public WebSite02() {
//
// }
public
WebSite02(String name, String domain) {
this
.name = name;
this
.domain = domain;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
String getDomain() {
return
domain;
}
public
void
setDomain(String domain) {
this
.domain = domain;
}
public
String toString() {
return
"名称:"
+ name +
"\n域名:"
+ domain;
}
}
public
class
InstanceDemo02 {
public
static
void
main(String[] args) {
try
{
Class<?> class2 = Class.forName(
"javase.reflex.WebSite02"
);
WebSite02 webSite = (WebSite02) class2.newInstance();
// 实例化WebSite对象
webSite.setName(
"zifangsky的个人博客"
);
webSite.setDomain(
"http://www.zifangsky.cn"
);
System.out.println(webSite);
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
catch
(InstantiationException e) {
e.printStackTrace();
}
catch
(IllegalAccessException e) {
e.printStackTrace();
}
}
}
|
运行时报错:
1
2
3
4
5
6
7
|
java.lang.InstantiationException: javase.reflex.WebSite02
at java.lang.Class.newInstance(Class.java:
427
)
at javase.reflex.InstanceDemo02.main(InstanceDemo02.java:
43
)
Caused by: java.lang.NoSuchMethodException: javase.reflex.WebSite02.<init>()
at java.lang.Class.getConstructor0(Class.java:
3082
)
at java.lang.Class.newInstance(Class.java:
412
)
...
1
more
|
(2)通过有参构造方法实例化对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
package
javase.reflex;
import
java.lang.reflect.Constructor;
import
java.lang.reflect.InvocationTargetException;
class
WebSite03 {
private
String name;
private
String domain;
/**
* 只有有参数构造方法
* */
public
WebSite03(String name, String domain) {
this
.name = name;
this
.domain = domain;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
String getDomain() {
return
domain;
}
public
void
setDomain(String domain) {
this
.domain = domain;
}
public
String toString() {
return
"名称:"
+ name +
"\n域名:"
+ domain;
}
}
public
class
InstanceDemo03 {
public
static
void
main(String[] args) {
try
{
Class<?> class3 = Class.forName(
"javase.reflex.WebSite03"
);
Constructor<?>[] cons = class3.getConstructors();
//申明一个构造方法数组
//取第一个构造方法,并且使用可变参数的形式向该构造方法传递参数
WebSite03 webSite = (WebSite03) cons[
0
].newInstance(
"zifangsky的个人博客"
,
"http://www.zifangsky.cn"
);
System.out.println(webSite);
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
catch
(InstantiationException e) {
e.printStackTrace();
}
catch
(IllegalAccessException e) {
e.printStackTrace();
}
catch
(IllegalArgumentException e) {
e.printStackTrace();
}
catch
(InvocationTargetException e) {
e.printStackTrace();
}
}
}
|
输出:
1
2
|
名称:zifangsky的个人博客
域名:http:
//www.zifangsky.cn
|
四 通过反射取得类的结构的常用操作示例
首先定义了一个接口和它的子类
接口:
1
2
3
4
5
6
7
8
|
package
javase.reflex;
public
interface
Animal {
public
final
String WATER =
"水"
;
public
void
drink();
public
void
eat();
public
String introduce(String name,
int
age);
}
|
它的子类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
package
javase.reflex;
public
class
Dog
implements
Animal{
private
String name;
private
int
age;
//三个构造方法
public
Dog() {
}
public
Dog(String name) {
this
.name = name;
}
public
Dog(String name,
int
age) {
this
.name = name;
this
.age = age;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
int
getAge() {
return
age;
}
public
void
setAge(
int
age) {
this
.age = age;
}
/**
* 喝水
* */
public
void
drink() {
System.out.println(
"每天喝"
+ WATER);
}
/**
* 吃东西
* */
public
void
eat() {
System.out.println(name +
": 啃骨头 + 吃肉"
);
}
/**
* 介绍
* */
public
String introduce(String name,
int
age) {
return
"我的名字是"
+ name +
",今年"
+ age +
"岁了"
;
}
}
|
一些常用操作示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
package
javase.reflex;
import
java.lang.reflect.Constructor;
import
java.lang.reflect.Field;
import
java.lang.reflect.Method;
import
java.lang.reflect.Modifier;
public
class
Demo {
/**
* 获取实现的接口
* */
public
void
getInterfacesDemo() {
try
{
Class<?> class1 = Class.forName(
"javase.reflex.Dog"
);
Class<?>[] inter = class1.getInterfaces();
// 获取所有接口
for
(Class<?> c : inter)
System.out.println(
"实现的接口: "
+ c.getName());
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取继承的父类
* */
public
void
getSuperDemo() {
try
{
Class<?> class1 = Class.forName(
"javase.reflex.Dog"
);
Class<?> superClass = class1.getSuperclass();
// 获取父类
System.out.println(
"父类: "
+ superClass.getName());
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取所有构造方法
* */
public
void
getConstructorsDemo() {
try
{
Class<?> class1 = Class.forName(
"javase.reflex.Dog"
);
Constructor<?>[] cons = class1.getConstructors();
// 获取所有构造方法
for
(Constructor<?> con : cons) {
Class<?>[] parameters = con.getParameterTypes();
// 获取一个构造方法的所有参数类型
int
mo = con.getModifiers();
// 取出权限
System.out.print(
"构造方法: "
+ Modifier.toString(mo) +
" "
);
// 输出权限名称
System.out.print(con.getName() +
"("
);
for
(
int
i =
0
; i < parameters.length; i++) {
System.out.print(parameters[i].getName() +
" arg"
+ i);
if
(i < (parameters.length -
1
))
System.out.print(
", "
);
}
System.out.println(
")"
);
}
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取所有方法
* */
public
void
getMethodsDemo() {
try
{
Class<?> class1 = Class.forName(
"javase.reflex.Dog"
);
Method[] methods = class1.getMethods();
for
(Method method : methods) {
System.out.print(
"方法: "
+ Modifier.toString(method.getModifiers()) +
" "
);
// 权限
System.out.print(method.getReturnType().getName() +
" "
);
// 返回值类型
System.out.print(method.getName() +
"("
);
// 方法名
// 参数
Class<?>[] parameters = method.getParameterTypes();
for
(
int
i =
0
; i < parameters.length; i++) {
System.out.print(parameters[i].getName() +
" arg"
+ i);
if
(i < (parameters.length -
1
))
System.out.print(
", "
);
}
System.out.print(
")"
);
// 抛出的异常
Class<?>[] exceptions = method.getExceptionTypes();
if
(exceptions.length >
0
)
System.out.print(
"throws "
);
for
(
int
i =
0
; i < exceptions.length; i++) {
System.out.print(exceptions[i].getName());
if
(i < (exceptions.length -
1
))
System.out.print(
","
);
}
System.out.println();
}
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取所有属性
* */
public
void
getFieldsDemo() {
try
{
Class<?> class1 = Class.forName(
"javase.reflex.Dog"
);
// 1 取得本类中的全部属性,(PS:普通代码块)
{
Field[] field = class1.getDeclaredFields();
for
(Field f : field) {
System.out.print(
"本类属性: "
+ Modifier.toString(f.getModifiers()) +
" "
);
// 权限
System.out.print(f.getType().getName() +
" "
);
// 类型
System.out.println(f.getName() +
";"
);
// 属性名称
}
}
// 2 取得实现的接口或父类中的公共属性
{
Field[] field = class1.getFields();
for
(Field f : field) {
System.out.print(
"公共属性: "
+ Modifier.toString(f.getModifiers()) +
" "
);
// 权限
System.out.print(f.getType().getName() +
" "
);
// 类型
System.out.println(f.getName() +
";"
);
// 属性名称
}
}
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
}
public
static
void
main(String[] args) {
Demo demo =
new
Demo();
demo.getInterfacesDemo();
System.out
.println(
"******************http://www.zifangsky.cn**********************\n"
);
demo.getSuperDemo();
System.out
.println(
"******************http://www.zifangsky.cn**********************\n"
);
demo.getConstructorsDemo();
System.out
.println(
"******************http://www.zifangsky.cn**********************\n"
);
demo.getMethodsDemo();
System.out
.println(
"******************http://www.zifangsky.cn**********************\n"
);
demo.getFieldsDemo();
System.out
.println(
"******************http://www.zifangsky.cn**********************\n"
);
}
}
|
输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
实现的接口: javase.reflex.Animal
******************http:
//www.zifangsky.cn**********************
父类: java.lang.Object
******************http:
//www.zifangsky.cn**********************
构造方法:
public
javase.reflex.Dog(java.lang.String arg0,
int
arg1)
构造方法:
public
javase.reflex.Dog(java.lang.String arg0)
构造方法:
public
javase.reflex.Dog()
******************http:
//www.zifangsky.cn**********************
方法:
public
java.lang.String getName()
方法:
public
void
setName(java.lang.String arg0)
方法:
public
int
getAge()
方法:
public
void
setAge(
int
arg0)
方法:
public
void
drink()
方法:
public
void
eat()
方法:
public
java.lang.String introduce(java.lang.String arg0,
int
arg1)
方法:
public
final
void
wait()
throws
java.lang.InterruptedException
方法:
public
final
void
wait(
long
arg0,
int
arg1)
throws
java.lang.InterruptedException
方法:
public
final
native
void
wait(
long
arg0)
throws
java.lang.InterruptedException
方法:
public
boolean
equals(java.lang.Object arg0)
方法:
public
java.lang.String toString()
方法:
public
native
int
hashCode()
方法:
public
final
native
java.lang.Class getClass()
方法:
public
final
native
void
notify()
方法:
public
final
native
void
notifyAll()
******************http:
//www.zifangsky.cn**********************
本类属性:
private
java.lang.String name;
本类属性:
private
int
age;
公共属性:
public
static
final
java.lang.String WATER;
******************http:
//www.zifangsky.cn**********************
|
五 通过反射调用类中的方法
注:下面的例子使用了前面定义过的javase.reflex.Dog类
(1)调用一般方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
package
javase.reflex;
import
java.lang.reflect.Constructor;
import
java.lang.reflect.Method;
public
class
InvokeDemo {
public
static
void
main(String[] args) {
//1 调用的方法无参,而且不涉及类中属性
{
try
{
Class<?> class1 = Class.forName(
"javase.reflex.Dog"
);
Method method = class1.getMethod(
"drink"
);
method.invoke(class1.newInstance());
}
catch
(Exception e) {
e.printStackTrace();
}
System.out
.println(
"******************http://www.zifangsky.cn**********************\n"
);
}
//2 调用的方法无参,但是涉及到类中的属性
{
try
{
Class<?> class1 = Class.forName(
"javase.reflex.Dog"
);
Constructor<?>[] cons = class1.getConstructors();
Method method = class1.getMethod(
"eat"
);
method.invoke(cons[
1
].newInstance(
"旺财"
));
//通过第二个有参数的构造方法初始化name属性
}
catch
(Exception e) {
e.printStackTrace();
}
System.out
.println(
"******************http://www.zifangsky.cn**********************\n"
);
}
//3 调用的方法有参数
{
try
{
Class<?> class1 = Class.forName(
"javase.reflex.Dog"
);
Method method = class1.getMethod(
"introduce"
,String.
class
,
int
.
class
);
String ret = (String) method.invoke(class1.newInstance(),
"旺财"
,
15
);
//有返回值
System.out.println(ret);
}
catch
(Exception e) {
e.printStackTrace();
}
}
}
}
|
输出:
1
2
3
4
5
6
7
|
每天喝水
******************http:
//www.zifangsky.cn**********************
旺财: 啃骨头 + 吃肉
******************http:
//www.zifangsky.cn**********************
我的名字是旺财,今年
15
岁了
|
(2)调用setter和getter方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
package
javase.reflex;
import
java.lang.reflect.Method;
public
class
InvokeGetSetDemo {
/**
* 通过反射调用Getter和Setter方法
* */
public
void
TestGetterSetter(){
try
{
Class<?> class1 = Class.forName(
"javase.reflex.Dog"
);
Object dog = class1.newInstance();
//实例化
setter(dog,
"name"
,
"大黄"
, String.
class
);
setter(dog,
"age"
,
4
,
int
.
class
);
//输出测试
System.out.println(
"名字: "
+ getter(dog,
"name"
));
System.out.println(
"年龄: "
+ getter(dog,
"age"
));
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
catch
(InstantiationException e) {
e.printStackTrace();
}
catch
(IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* setter方法
* @param object 实例化的对象
* @param str 要设置的属性名称
* @param value 属性值
* @param type 属性类型
* */
public
void
setter(Object object,String str,Object value,Class<?> type){
try
{
//获取setter方法,如:setName。其中要将属性的首字母大写
Method method = object.getClass().getMethod(
"set"
+ UpperString(str), type);
method.invoke(object, value);
//setter方法无返回值
}
catch
(Exception e) {
e.printStackTrace();
}
}
/**
* getter方法
* @param object 实例化的对象
* @param str 属性名称
* @return 返回属性
*
* */
public
Object getter(Object object,String str){
try
{
//获取getter方法,如:getName。其中要将属性的首字母大写
Method method = object.getClass().getMethod(
"get"
+ UpperString(str));
return
method.invoke(object);
//getter方法有返回值
}
catch
(Exception e) {
e.printStackTrace();
}
return
null
;
}
/**
* 将字符串的首字母改成大写
* */
public
String UpperString(String str){
return
String.valueOf(str.charAt(
0
)).toUpperCase() + str.substring(
1
);
}
public
static
void
main(String[] args) {
new
InvokeGetSetDemo().TestGetterSetter();
}
}
|
输出:
1
2
|
名字: 大黄
年龄:
4
|
附:
(1)我们在使用eclipse这类开发工具进行程序开发时,一般在我们输入一个“.”时,就可以提示出这个类的所有方法,这个功能实际上就是用了反射的原理 –> 通过反射获取一个类的所有方法
(2)将Java中的.class文件反编译成.java文件实际上也是应用了反射的原理
本文转自 pangfc 51CTO博客,原文链接:http://blog.51cto.com/983836259/1741355,如需转载请自行联系原作者