JAVA基础巩固加强 enhance day1反射 reflect以前一直只知道有reflect这么一个类是用来反射的,听人家说java
JAVA基础巩固加强 enhance day1反射 reflect
以前一直只知道有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
综上可以看出,其实反射也没多难,人家那些写框架的也不就是用了些反射吗?把配置文件中的东西读出来,然后再调用下面的类去做应该做的事情,当然这个过程就用到了反射了。