以前一直只知道有reflect这么一个类是用来反射的,听人家说java中的反射很难,晚上听罢张老师讲的反射这一节的内容,惶然大悟,原来反射就是把Java类中的各种成分映射成相应的java类。
反射的基础是要掌握Class这个类的,具体Class的类是干什么的,下面是api文档中的解释
api中关于Class类的一段描述
Instances of the class
Class
represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class that is reflected as a
Class
object that is shared by all arrays with the same element type and number of dimensions. The primitive Java types (
boolean
,
byte
,
char
,
short
,
int
,
long
,
float
, and
double
), and the keyword
void
are also represented as
Class
objects.
翻译成中文
Class
类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该
Class
对象。基本的 Java 类型(
boolean
、
byte
、
char
、
short
、
int
、
long
、
float
和
double
)和关键字
void
也表示为
Class
对象。
可以看出Class类就是一个类或者接口对象的一个实例在内存中的字节码,而如何得到一个类的字节码呢?其方法有三:
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
1
Class
<?
extends
String
>
cls1
=
str1.getClass();
2
Class
<
String
>
cls2
=
String.
class
;
3
Class
<?>
cls3
=
Class.forName(
"
java.lang.String
"
);
而Class的isPrimitive()方法就是用来判断一个类的字节码是不是9个预定义的class
接下来是Constructor类,Constructor类代表某个类中的一个构造方法。
得到某个类所有的构造方法: 例子:
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
Constructor [] constructors
=
Class.forName(
"
java.lang.String
"
).getConstructors();
得到某一个构造方法:
例子:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->
Constructor constructor
=
Class.forName(“java.lang.String”).getConstructor(StringBuffer.
class
);
//
获得方法时要用到类型
创建实例对象:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->
//
通常方式:
String str
=
new
String(
new
StringBuffer(
"
abc
"
));
//
反射方式:
String str
=
(String)constructor.newInstance(
new
StringBuffer(
"
abc
"
));
//
调用获得的方法时要用到上面相同类型的实例对象
Class.newInstance()方法:
例子:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->
String obj
=
(String)Class.forName(
"
java.lang.String
"
).newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
该方法内部的具体代码是怎样写的呢?用到了缓存机制来保存默认构造方法的实例对象。
下面是一个Field反射的综合实例
将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改成"a"。
首先定义一个ReflectPoint的类
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->
1
package
com.anduo.day1;
2
3
public
class
ReflectPoint {
4
private
int
x;
5
public
int
y;
6
public
String a
=
"
ball
"
;
7
public
String b
=
"
basketball
"
;
8
public
String c
=
"
hello
"
;
9
10
public
ReflectPoint(
int
x,
int
y) {
11
super
();
12
this
.x
=
x;
13
this
.y
=
y;
14
}
15
16
@Override
17
public
String toString() {
18
return
"
a=
"
+
a
+
"
;b=
"
+
b
+
"
;c=
"
+
c;
19
}
20
}
21
下面的步骤是:先从对象中得到所有为String类型的字段,2:得到Sting字段的值;3:用String类的replace方法代换a字符为b字符;4:把对象的String字段设置为修改完的新String。
齐活儿
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->
1
package
com.anduo.day1;
2
3
import
java.lang.reflect.Constructor;
4
import
java.lang.reflect.Field;
5
6
public
class
ReflectTest {
7
8
9
public
static
void
main(String[] args)
throws
Exception {
10
11
12
/**
13
* 成员变量的反射 Field
14
*/
15
System.out.println(
"
**成员变量的反射 Field**
"
);
16
ReflectPoint pt1
=
new
ReflectPoint(
1
,
-
1
);
17
Field fieldY
=
pt1.getClass().getField(
"
y
"
);
18
//
fieldY 不是对象身上的变量,而是类上,要用它来去对象上字段的值
19
System.out.println(
"
p1 中 y =
"
+
fieldY.get(pt1));
20
Field fieldX
=
pt1.getClass().getDeclaredField(
"
x
"
);
//
获取私有属性字段
21
fieldX.setAccessible(
true
);
//
暴力反射
22
System.out.println(
"
p1 中 x =
"
+
fieldX.get(pt1));
23
24
/**
25
* 将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改成"a"
26
*/
27
changeStringValue(pt1);
28
System.out.println(pt1);
29
}
30
31
/**
32
* 将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改成"a"
33
*
@param
obj
34
*
@throws
IllegalArgumentException
35
*
@throws
IllegalAccessException
36
*/
37
private
static
void
changeStringValue(Object obj)
throws
IllegalArgumentException, IllegalAccessException {
38
Field[] fields
=
obj.getClass().getFields();
39
for
(Field field : fields) {
40
//
if(field.getType().equals(String.class))
41
if
(field.getType()
==
String.
class
) {
42
String oldValue
=
(String) field.get(obj);
43
String newValue
=
oldValue.replace(
'
a
'
,
'
b
'
);
44
field.set(obj, newValue);
45
}
46
}
47
}
48
49
}
50
结果如下
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->
**
成员变量的反射 Field
**
p1 中 y
=
-
1
p1 中 x
=
1
a
=
bbll;b
=
bbsketbbll;c
=
hello
综上可以看出,其实反射也没多难,人家那些写框架的也不就是用了些反射吗?把配置文件中的东西读出来,然后再调用下面的类去做应该做的事情,当然这个过程就用到了反射了。