一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象后,得到这些实例对象后有什么用呢?怎么用呢?这正是学习和应用反射的要点。
二、反射的基石——Class类
1、java中所有的类文件都有共同属性,所以可以向上抽取,把这些共性内容封装成一个类,这个类就叫Class。它的实例对象就是各个类在内存中的字节码。
什么叫字节码?
当源程序中用到类时,首先要从硬盘把这个类的那些二进制代码(一个类编译成class放在硬盘上以后,就是一些二进制代码),加载到内存中里面来,再用这些字节码去复制出一个一个对象来。
2、获取Class对象的三种方式
1)第一种方式:通过对象的getClass方法进行获取。
如:Class clazz=new Person().getClass();//Person是一个类名,但每次都需要具体的类和该类的对象,以及调用getClass方法。
2)第二种方式:任何数据类型都具备着一个静态的属性class,这个属性直接获取到该类型的对应Class对象。
如:Class clazz=Person.class;//Person是一个类名
比第一种较为简单,不用创建对象,不用调用getClass方法,但是还是要使用具体的类,和该类中的一个静态属性class完 成。
3)第三种方式:通过Class类中的forName()方法。
Class.forName("类名"),例如,Class.forName("java.util.Date");
三、Constructor类
Constructor类代表某个类中的一个构造方法
1.得到某个类所有的构造方法:
例子:Constructor [] constructors= Class.forName("java.lang.String").getConstructors();
2.得到某一个构造方法:
例子: Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);
//获得构造方法时要明确该构造方法的参数类型
创建实例对象:
通常方式:String str = new String(new StringBuffer("abc"));
//使用获得的构造方法newInstance时,要将该构造方法的参数类型的实例对象传入进来。
反射方式: String str = (String)constructor.newInstance(new StringBuffer("abc"));
Class.newInstance()方法:
例子:String obj = (String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
该方法内部的具体代码是怎样写的呢?用到了缓存机制来保存默认构造方法的实例对象。
四、Field类
1、Field类代表某个类中一个成员变量
2、获取Field方法
Field getField(String s);//只能获取公有和父类中公有
Field getDeclaredField(String s);//获取该类中任意成员变量,包括私有
setAccessible(ture); //如果是私有字段,要先将该私有字段进行取消权限检查的能力。也称暴力访问。
set(Object obj, Object value);//将指定对象变量上此Field对象表示的字段设置为指定的新值。
Object get(Object obj);//返回指定对象上Field表示的字段的值。
五、Method类
1、概述:Method类代表某个类中的一个成员方法。
2、专家模式:谁拥有这个数据或方法,谁就是在调用这个数据或方法的专家。
如人关门:
调用者:是门调用关的动作,对象是门,因为门知道如何执行关的动作,通过门轴之类的细节实现。
指挥者:是人在指挥门做关的动作,只是给门发出了关的信号,让门执行。
如列车长让火车停下来
调用者:是火车通过调用并使用自身的刹车制动系统是自身停止下来。
总结:变量使用方法,是方法本身知道如何实现执行的过程,也就是“方法对象”调用方法,才执行了方法的每个细节的。
3、获取的方法
Method[] getMethods();//只获取公共和父类中的方法。
Method[] getDeclaredMethods();//获取本类中包含私有。
Method getMethod("方法名",参数.class(如果是空参可以写null));
Object invoke(Object obj ,参数类型);//调用方法
如果方法是静态,invoke方法中的对象参数可以为null。
如:
获取某个类中的某个方法:(如String str =”abc”)
1)通常方式:str.charAt(1)
2)反射方式:
Method charAtMethod =Class.forName(“java.lang.String”).getMethod(“charAt”,int.class);
charAtMethod.invoke(str,1);
说明:如果传递给Method对象的invoke()方法的第一个参数为null,说明Method对象对应的是一个静态方法