一:反射的基石 |
1:反射技术创建在jdk提供的Class类上,所以要掌握反射技术,首先要熟悉Class类。java
2:经过Class类就能够获得java类中方方面面的内容<如:java类中的:构造方法(Constructor)、属性(field)、方法(method)>。spring
3:Class cls=?(?表明什么,你知道吗?)编程
注:?表明字节码数组
4:什么是字节码?tomcat
注:java代码编译的时候,将java源程序翻译成字节码<.class>存储到硬盘上,而后类加载器将字节码加载到jvm的内存中,生成一个又一个java对象。 框架
5:获得字节码的三种方式:jvm
String str1="abc"ide
Class cls1=str1.getClass();<经过对象获得字节码>测试
Class cls2=String.class;<经过类获得字节码>this
Class cls3=Class.forName("java.lang.String");<经过包名获得字节码>
注:获得了一个类的字节码,那么就能够获得字节码的所有成分,下面将一一介绍.
6:同一类型的字节码相同吗?
System.out.println(cls1==cls2);返回:true
System.out.println(cls1==cls3);返回:true
注:说明同一类型的字节码只有一份,同一类型的字节码是相同的。
二:字节码的简单应用<检测数据的类型> |
1: String str1="abc";
Class cls1=str1.getClass();
//测试String是否为基本类型的字节码,返回false;由于:String是一个类 System.out.println(cls1.isPrimitive());
2: //int是基本类型的字节码,返回true
System.out.println(int.class.isPrimitive())
3: //int是基本类型,Integer是类,所以返回:false
System.out.println(int.class==Integer.class);
4: //包装类型的基本类型的字节码比较,返回true
System.out.println(int.class==Integer.TYPE);
5://数组不是基本类型,返回false
System.out.println(int[].class.isPrimitive());
三:反射调用类中构造方法 |
//从String类字节码中得的:参数为:StringBuffer的构造方法类 Constructor cons=String.class.getConstructor(StringBuffer.class);
//用获得的构造方法类来建立一个String类型的实例
String str3=(String)cons.newInstance(new StringBuffer("abcd"));
//用获得的实例调用方法
System.out.println(str3.charAt(3));
四:反射获取类中的属性--简单应用 |
1:定义类(ReflectPoint)<下面用反射技术获取该类的属性>以下:
public class ReflectPoint {
private int x;//私有的属性,注意看下面,反射怎样访问私有属性!
public int y;
public String str1="bal";
public String str2="bseerb";
public String str3="hjke";
/**
* 注意:右键->source-Construtor能够自动生成构造方法
* @param x
* @param y
*/
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;}
public String toString(){
return str1+":"+str2+":"+str3;
}}
2:使用反射技术,从ReflectPoint字节码中获得属性y,代码以下:
ReflectPoint rfp1=new ReflectPoint(3, 5);
//从ReflectPoint的字节码中获得名为y的属性
Field fieldY=rfp1.getClass().getField("y");
//从rfp1这个对象上去取值
System.out.println(fieldY.get(rfp1)); 结果为:5
3:使用反射技术,从ReflectPoint字节码中获得私有属性x,代码以下:
ReflectPoint rfp1=new ReflectPoint(3, 5);
Field fieldX=rfp1.getClass().getDeclaredField("x");
//由于x设置的权限为:private,所以设置强制性访问变量,这叫暴力反射 ,
fieldX.setAccessible(true);
System.out.println(fieldX.get(rfp1)); 结果为:3
五:反射改变类中的属性值-综合案例应用 |
1:问题?
将类名为:ReflectPoint类中的String类型的成员变量对应的字符串内容的 "b"-改成-->"a"
2:定义类以下<用反射来改变这个类中的属性>:
public class ReflectPoint {
public String str1="bal";
public String str2="bseerb";
public String str3="hjke";
}
3:反射方法代码:
private static void changeStringValue(Object obj) throws IllegalArgumentException, IllegalAccessException {
//获得obj字节码中的所有属性
Field[] fields=obj.getClass().getFields();//遍历
for(Field field:fields){
//若是是String类型
if(field.getType()==String.class){
//取得值
String oldValue=(String) field.get(obj);
String newValue=oldValue.replace('b','a');
field.set(obj, newValue);
} }}
4:测试代码:
ReflectPoint rfp1=new ReflectPoint();
changeStringValue(rfp1);
5:结果:
str1=aal str2 = aseera str3 = hjke 反射改变属性值成功!
六:反射调用类中的方法 |
1:经过反射调用string类中charAt方法
String str1="abc";
//从string字节码中获得名为:charAt,参数类型为int.class的方法
Method methodChAt=String.class.getMethod("charAt",int.class); //注:invoke(str1,1)表示:对象str1调用charAt方法,传入参数为:1
System.out.println(methodChAt.invoke(str1,1));
七:总结 |
1:掌握了以上知识,就掌握了java反射机制的基础和精髓部分。但运用反射机制到实际软件系统中,在反射的世界里,才刚刚开始。
2:反射通常用于开发框架<如:struct/spring/Hibernate>,这些框架都是以反射技术做为支撑的。
3:掌握了反射技术便于读懂较深刻的java代码<借张孝祥的话>,我也有这样的体会。<研究tomcat源码时候,里面就运用了大量的反射技术>。
ps:在编程道路上|我才刚刚起步|加油|坚持!
2012-10-4 coder:亮仔