反射
反射的基石:Class类
Java程序中的各个Java类属于同一类事物,描述这类事物的java类名就是Class。
一个类被类加载器加载到 内存中,占用一片空间,这个空间里的内容就是类的字节码,不同的类的字节码是不同的,所以他们在内存中的内容是不同的,只一个个空间可以分别用一个个对象来表示这些对象的类型就是Class。
获取Class的实例对象的几种方法:
1.通过每个对象都具有的getClass方法。new Date().getClass,很明显,需要创建指定的对象
2.每一个数据类型都有的静态class方法,类名.class,System.class必须明确这个类
3.通过Class类中提供的静态方法forName(),Class.forName("类名"),
反射就是把Java类中的各种成分映射成相应的java类,例如,一个java类中用一个Class的对象来表示,一个类中的组成部分:成员变量、方法、构造方法等也都用一个个java类来表示。表示java类的Class类会提供相应的方法来获取其中的信息,这些信息也用相应的类实例对象来表示,如方法,Method构造方法Contructor等
一、构造方法得反射应用
Constructor类表示某个类中的构造方法。
1.得到某个类的所有构造方法:通过getConstructors()方法
例:Constructor[] cons=Class.forName("java.lang.String").getConstructors();
2.得到某一个构造方法,此时需要指定类型
例:Construtor cons=Class.forName("java.lang.String").getConstructors(StringBuffer.class)
3.得到方法后就可以创建所需的实例对象了。
传统方法:String str=new String(new StringBuffr("abc"))
反射方式(用到上面相同的类型):String str=(String)cons.newInstance(new StringBuffer("abc"))
二、成员变量的反射
Field类表示某个类中的一个成员变量。
举例说明用法:
有这样的对象Point pt1=new Point(3,5);5是私有的,用反射取得3和5
1.获取Field类实例:
Field fildx=pt1.getClass().getFields("x");
那么fildx.get(pt1)就是3
2.5是私有的需要用getDeclareField方法获取
Field fildy=pt1.getClass().getDeclareField("y")
然后用setAccessible(true)设置可以强制使用,暴力反射
filedy.setAccseeible(true)
最后用get方法获取即可
package xiaobing;
import java.lang.reflect.*;
/*
* 将任意一个对象中的所有String类型的成员变量所对
* 应的字符串内容中的b改为a
*/
public class FieldDemo {
public static void main(String[] args)throws Exception
{
RefleectPoint pt1=new RefleectPoint();
changeStringValue(pt1);
System.out.println(pt1);
}
public static void changeStringValue(Object obj)throws Exception
{
//获取所有成员变量实例
Field[] fi=obj.getClass().getFields();
for(Field f:fi)
{
if(f.getType()==String.class)//比较字节码用==
{
String oldValue=(String)f.get(obj);//获取成员变量
String newValue=oldValue.replace("b", "a");
f.set(obj, newValue);
}
}
}
}
package xiaobing;
public class RefleectPoint {
public String str1="ball";
public String str2="basketball";
public String str3="itcaset";
public String toString()
{
return str1+"..."+str2+"..."+str3;
}
}
三、成员方法的反射。
Method类表示某个类中的一个成员方法。
1.先用getMethod()获取某一个方法
例: Method charAt=Class.forName("java.lang.String").getMethod("charAt",int.class);
用invole()方法调用获取,例:charAt.invoke(str,1),传统调用为str.charAt(1)
package xiaobing;
import java.lang.reflect.*;
/*
* 需求获取String的CharAt方法
*/
public class MethodDemo {
public static void main(String[] args) throws Exception
{
// TODO Auto-generated method stub
String str="abc";
System.out.println(str.charAt(1));//传统调用
//getMethod(需要的方法名,参数个数)
Method methodCharAt=String.class.getMethod("charAt", int.class);
System.out.println(methodCharAt.invoke(str, 1));
}
}
注意:如果传递给Method对象扥invoke方法得第一个参数是null,表示对应的是一个静态方法。