java的反射机制(Reflection)_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > java的反射机制(Reflection)

java的反射机制(Reflection)

 2010/12/29 8:10:59  lganggang131  http://lganggang131.javaeye.com  我要评论(0)
  • 摘要:今天复习了Java的反射机制,说实话,对于这方面的知识自己以前只是了解一点,并没有透彻的研究理解过,今天通过听张老师的视频,对java反射机制有了整体上的一个理解,反射就是把java中的各种成分映射成各种java类(真是类外有类啊),java反射机制允许程序在运行时透过ReflectionAPIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public,static等等)、superclass(例如Object)、实现之interfaces
  • 标签:Java 反射 反射机制

今天复习了Java的反射机制,说实话,对于这方面的知识自己以前只是了解一点,并没有透彻的研究理解过,今天通过听张老师的视频,对java反射机制有了整体上的一个理解,反射就是把java中的各种成分映射成各种java类(真是类外有类啊),

java反射机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等等)、superclass(例如Object)、实现之interfaces(例如Serializable),也包括fields和methods的所有信息,并可于运行时改变fields内容或调用methods。

在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中

??? Class类:代表一个类。

??? Constructor 类:代表类的构造方法。
??? Field 类:代表类的成员变量(成员变量也称为类的属性)。
? Method类:代表类的方法。
??? Array类:提供了动态创建数组,以及访问数组的元素的静态方法

??? 一、Class类?? ( Class类,反射的基石,)

??? Class类是Reflection API 中的核心类,它有以下方法
? getName():获得类的完整名字。
? getFields():获得类的public类型的属性。
? getDeclaredFields():获得类的所有属性,

? getMethods():获得类的public类型的方法。
? getDeclaredMethods():获得类的所有方法。

??? getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数 指定方法的参数类型。
??? getConstructors():获得类的public类型的构造方法。
??? getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
??? newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

二、Constructor类

???? 1、获得某个类的所有构造方法:Constructor[] constructors = Class.forName("java.lang.String").getConstructors();

???? 2、获得某个类的某个构造方法:Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);//获得构造方法时要指明参数类型,注意,在编译阶段编译器并不知道constructor是谁的构造方法,只有到程序运行时才知道是String的构造方法。

???? 3、创建实例对象方式有两种:

???????? 常用方式:String str = new String(new StringBuffer("itcast"));

???????? 反射方式:String str = (String)constructor.newInstance(new StringBuffer("heima"));//注意要强制类型转换,另外注意传递参数的一致性,即得到构造方法的参数类型与实例化构造方法的参数类型要一致,若将上述方式改成这样,String str = (String)construtor.newInstance("CSDN");这样的话,编译期虽然能够通过,但是运行时会报类型不匹配的异常

三、Filed类

??? public class Point{

???????? private int x;

???????? public?? int y;

?????? ............这里为xy的构造方法

??? }

???? public class TestReflect{

???? ............只写了相关代码,部分代码省略

???? Point p = new Point(12,3);

???? Field fieldY = p.getClass().getField("y");

???? System.out.println(fieldY.get(p));//打印出来应该为12,

???? System.out.println(fieldY);//打印出来为变量的定义,我这里是 public int com.itcast.Test.Point.y

????

???? Field fieldX = p.getClass.getDeclaredField("x");//因为x声明为私有变量,要用getDeclaredField(type arg)才能拿到,

???? fieldX.setAccessible(true);//由于x为私有变量,对上面拿到的fieldX还要进行设置可访问后才能够用,这也叫暴力反射

???? System.out.println(fieldX.get(p));

???? ............

??? }

注意fieldY不是对象p上的变量,而是代表字节码文件上的一个变量,所以取变量x的值应该到对象p上去取,如fieldY.get(p)

四、 Method类

Class.getMethod方法的时候接受哪些参数?显然要一个方法名,可以是同名的方法有多个,这又怎么识别出哪一个呢?这就需要靠参数类型和参数个数了。参数类型用什么来表示啊?用Class,例如,int.class,String.class等
Method.invoke()接受哪些参数,如果一个参数为null,表示的是调用这个方法不需要对象,从侧面说明了是静态方法!

题目:要你写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法。
public class TestReflect{

..........部分代码略

? String startingClassName = args[0];
? Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);
? //mainMethod.invoke(null, new Object[]{new String[]{"a","b","c"}});
??? mainMethod.invoke(null, (Object)new String[]{"a","b","c"});

...........

class TestArguments{
? public static void main(String[] args){
???? for(String arg : args){
???? System.out.println(arg);
???? }

.............

?? }
?? }因为方法的重载,main方法可能会有多个,到底选哪一个呢?getMethod("main", args);中的第二个参数,就是指定要选择的那个main方法的参数类型,根据参数类型与个数,Method就知道去调用哪一个main方法了。
由于我们知道main方法的参数是String [] args,所以,String[].class来表示他的类型,mainMethod.invoke(null, (Object)new String[]{"a","b","c"});中的第一个参数是null,不是一个对象,那说明不用对象即调用这个方法,那么,这个方法应该是静态方法,第二个参数,就是传递给main方法的参数。
?
??? 在给main方法传递参数时,不能使用如下代码mainMethod.invoke(null, new new String[]{"a","b","c"}});虽然这符合jdk1.5的语言要求,但是,jdk把它理解成了jdk1.4,对这个String数组进行了拆包,所以,出现了参数类型不对的问题。对于传数组的情况,只能按jdk1.4的语法进行调用,因为如果参数类型就是Object,它是没有办法区别的。

五、Array类

Array工具类用于完成对数组的反射操作

public class TestReflect{

........

public static void main(String[] args){

?? ....

?? String [] a1 = new String[]{"a","b","c"};

?? printObject(a1);
?? printObject("abc");

?? ....

}

?private static void printObject(Object obj) {
??? Class clazz = obj.getClass();
??? if(clazz.isArray()){?????????????????????????????????????? //判断传入的对象是不是数组,??????????????????
??????? int len = Array.getLength(obj);?????????????? //利用反射工具类Array得到数组的长度
??????? for(int i=0;i<len;i++){???????????????????????????? //循环遍历数组
??????? System.out.println(Array.get(obj, i));????? //拿到数组的第i个值。
??????? }
???? }else{
??????? System.out.println(obj);
?? }
? ......
?}

?

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lganggang131/archive/2010/12/28/6103893.aspx

发表评论
用户名: 匿名