反射的基石-Class类
反射就是把java类中的各种成分映射成相应的java类,java反射机制就是在运行状态中,对于任意个类,都能够知道这个类 的所有属性和方法;对于任意一个对象,都能够调
它的任意一个方法和属性,这种动态获取信息以及动态调用对象的方法的功能称之为java语言的反射机制。
该机制允许程序通过Reflect APIs取得任何已知名称的class的内部信息,例如modifiers(public ,private),superclass(object),interface(Cloneable),也包括基本数据类型,
机制可于运行时改变fields内容和methods。
关于动态语言:一般认为,程序在运行时,可改变程序的结构或者变量类型的语言。
java因有了Reflect,使其具有动态语言的特性,我么可以在程序运行时,加载使用编译期间完全位置的classes,即java可以加载在运行时才得知名称的class并获得其完整构造,生成对象实体,设置field,访问method。这种看透class的能力被称为Introspection(内省)。
Class的产生:当一个类被加载或被jvm调用,jvm会自动产生一个Class object。由于Class的构造方法是私有的,所以不能通过自定义对象的方式产
Class object 诞生管道 | 示例 |
运用getClass() 注:每个class 都有此函数 | String str = "abc"; Class c1 = str.getClass(); |
运用 Class.getSuperclass()2 | Button b = new Button(); Class c1 = b.getClass(); Class c2 = c1.getSuperclass(); |
运用static method Class.forName() (最常被使用) | Class c1 = Class.forName ("java.lang.String"); Class c2 = Class.forName ("java.awt.Button"); Class c3 = Class.forName ("java.util.LinkedList$Entry"); Class c4 = Class.forName ("I"); Class c5 = Class.forName ("[I"); |
运用 .class 语法 | Class c1 = String.class; Class c2 = java.awt.Button.class; Class c3 = Main.InnerClass.class; Class c4 = int.class; Class c5 = int[].class; |
运用 primitive wrapper classes 的TYPE 语法
| Class c1 = Boolean.TYPE; Class c2 = Byte.TYPE; Class c3 = Character.TYPE; Class c4 = Short.TYPE; Class c5 = Integer.TYPE; Class c6 = Long.TYPE; Class c7 = Float.TYPE; Class c8 = Double.TYPE; Class c9 = Void.TYPE; |
java反射机制的主要功能:
1.在运行时判断任意一个对象所属的类;
2.在运行时构造任意一个类的对象;
3.在运行时判断任意一个类所具有的成员变量和方法;
4.在运行时调用任意一个对象的方法;
5.生成动态代理。
字节码:当类被加载到内存中,占用内存中的一片空间,该空间里面的内容就是类的字节码,不同类的字节码是不同的。
获取字段值:
package net.csing;
import java.lang.reflect.*;
public class FieldDemo {
/**
* @param args
*/
public static void main(String[] args){
//创建要操作的对象。
ReflectPoint rf=new ReflectPoint(2,3);
try{
/*
* 获取public字段的值。
*/
Field fx=rf.getClass().getField("x");
//获取字段fx所对应的在某对象rf上的值
System.out.println("x:"+fx.get(rf));
/*
* 获取private字段的值。
*/
Field fy=rf.getClass().getDeclaredField("y");
fy.setAccessible(true);
//获取字段f所对应的在某对象rf上的值
System.out.println("y:"+fy.get(rf));
}
catch(Exception e){
throw new RuntimeException("error.");
}
}
}
class ReflectPoint{
public int x;
private int y;
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
字段遍历及字符替换
package net.csing;
import java.lang.reflect.*;
public class FieldDemo {
/**
* @param args
*/
public static void main(String[] args){
//创建要操作的对象。
ReflectPoint rf=new ReflectPoint(2,3);
try{
/*
* 获取public字段的值。
*/
Field fx=rf.getClass().getField("x");
//获取字段fx所对应的在某对象rf上的值
System.out.println("x:"+fx.get(rf));
/*
* 获取private字段的值。
*/
Field fy=rf.getClass().getDeclaredField("y");
fy.setAccessible(true);
//获取字段f所对应的在某对象rf上的值
System.out.println("y:"+fy.get(rf));
/*
* 将对象对应的字段中的含有b的字符串全部替换成a
*/
changeStringChar(rf);
//打印结果
System.out.println(rf);
}
catch(Exception e){
throw new RuntimeException("error.");
}
}
private static void changeStringChar(ReflectPoint rf) {
/*
* 获取对像对应的所有字段。
*/
Field[] field=rf.getClass().getFields();
try{
//遍历字段。
for(Field f:field ){
//筛选string字段。
if(f.getType()==String.class){
//获得字段对应的值。
String oldStr=(String)f.get(rf);
//将b替换为a
String newStr=oldStr.replace('b', 'a');
//将替换后的结果写入对象。
f.set(rf,newStr);
}
}
}
catch(Exception e){
throw new RuntimeException("error.");
}
}
}
//操作字段的反射类。
class ReflectPoint{
public int x;
private int y;
public String str1="abcdefg";
public String str2="abcdefgijkla";
public String str3="efg";
//初始化x,y
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
//重写该类对应的toString方法。
public String toString(){
return str1+":"+str2+":"+str3;
}
}
反射的作用:实现框架功能
框架与工具类有区别:工具类被用户的类调用;而框架则调用用户提供的类。
用户要用框架,则框架如何调用随后用户书写的类,此时需要用到反射。
javabean实例
javabean是一种特殊的java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有 的字段,如果要在两个模块间传递多个信息,可将该信息封装到javabean中,这些信息在类中用私有字段来存储。javabean的属性是根据方法名来判断出来的,一般如getName去掉get,Name即是属性名。jdk中提供了对javabean操作的api,这套api称为内省,用内省来访问私有化的成员和变量非常方便。
package csing.net;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class IntroSpectionDemo {
/**
* @param args
* @throws IntrospectionException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static void main(String[] args) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
ReflectDemo rd=new ReflectDemo(6,9);
String propertyName="x";
/*
* PropertyDescriptor:描述javabean中propertyName的属性。
*/
//获得属性对象。
PropertyDescriptor pd=new PropertyDescriptor(propertyName,rd.getClass());
//获得propertyName对应的方法。
Method methodGetX=pd.getReadMethod();
try {
//使用方法获取X的值。
Object retVal=methodGetX.invoke(rd);
System.out.println(retVal);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
/*
* 获取设置属性的方法。
*/
Method methodSetX=pd.getWriteMethod();
//方法引用。
methodSetX.invoke(rd, 19);
//获取方法,取得值。
int retVal2=rd.getX();
System.out.println(retVal2);
//通过beanInfo可获得对象对应的属性,方法等。
BeanInfo bi=Introspector.getBeanInfo(rd.getClass()); //根据对象获得Class
//获得属性集
PropertyDescriptor[] pd2=bi.getPropertyDescriptors();
//遍历属性集
for(PropertyDescriptor p:pd2){
System.out.println("get read method:");
if(p.getName().equals(propertyName)){
//获得特定的属性。
System.out.println("I got his name:"+p.getName());
}
//获得对象的get方法。
Method m=p.getReadMethod();
Object get_x=m.invoke(rd);
System.out.println(get_x);
}
}
}
//反射测试类。
class ReflectDemo{
public ReflectDemo(int x, int y) {
super();
this.x = x;
this.y = y;
}
private int x=0;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
private int y=0;
}