黑马程序员技术交流社区

标题: 反射 [打印本页]

作者: 班志国    时间: 2012-10-30 19:34
标题: 反射
要反射哪个类 我们不是提前已经知道要反射的类当中的方法及属性了吗 那反射干嘛还要有得到字段类型的方法?
作者: 毕影彬    时间: 2012-10-30 19:38
你可以用反射知道一个陌生的类中,包含什么方法和属性等等。 而且,反射不只如此,比如后期对于MVC设计中,会大量用到反射和接口,一起实现层与层之间的分离。 如果你看了毕老实,关于Properties的讲解,你应该能体会到这一点。
作者: 静等花开    时间: 2012-10-30 19:41
比如可以获得该类的构造方法,获得该类的成员变量以及所有的方法;
如何获得构造方法并进行调用?
         假设我们最后要完成的功能是实现new String(new StringBuffer(“abc”))的功能,通过反射来实现的话,首先我们要得到String的Class对象,然后再利用Class类的获得构造方法的方法来得到构造方法,然而Class类中有两个这样的方法①Construtor<T> getConstructor(Class<?>…parameterType);②Constructor<?>[] getConstructors() ;第一个方法是用来得到某个确定的构造方法,如我们现在就是要获得参数为StringBuffer的构造方法,那么我们就可用这个构造方法,不过这里面的参数列表都是Class对象的,所以我们调用的时候就StringBuffer.class才行。第二个方法是用来获得该类中所有的构造方法;对于这两个方法最后都是返回一个Constructor对象的,就是说把那个要操作的类的构造方法封装为一个对象,然后利用该对象中的方法进行对象的实例化等。
         现在来实现上面说的new String(new StringBuffer(“abc”)):         [java] view plaincopyprint?Constructor c = String.class.getConstructor(StringBuffer.class);  
String s = (String)c.newInstance(new StringBuffer(“abc”));  

Constructor c = String.class.getConstructor(StringBuffer.class);
String s = (String)c.newInstance(new StringBuffer(“abc”));         在这个过程中我们得到了确定的构造方法,然后调用Constructor类中的newInstance(Object参数)这个方法返回一个实例对象,如果之前在声明该Class对象是String类型的话,这里就是String类型的对象。
         获得构造方法才是开始,同样我们可以通过反射来获得某个类的成员变量,并把该变量封装为Field类型的对象。同样是利用该Field中的方法得到该字段的值,通过set方法来设置对象这个字段的值;这两个方法是:Object get(Object obj)和void set(Object obj,Object value);
现在假设某个类A中有两个成员变量private int x;public int y;然后我们想通过反射来获得这个类的对象的两个成员变量:【A类的对象 AA(3,4)】       [java] view plaincopyprint?Field field = AA.getClass().getFeild(“y”); //获得y属性的字段并封装为Field的对象   
field.get(AA);//获得AA对象在field字段的值  

Field field = AA.getClass().getFeild(“y”); //获得y属性的字段并封装为Field的对象
field.get(AA);//获得AA对象在field字段的值        如果要获得x的值,由于是私有属性,那么在获得属性字段的时候就必须使用另一个方法来使得我们可以看到这个私有的字段。看是看到了,如果想获得该字段的值,还要使用一个字段可使用的函数设置为真,否则就不能进行相关的操作了。      [java] view plaincopyprint?Field field = AA.getClass().getDeclaredFeild(“x”);  
field.setAccessible(true);  
field.get(AA);  

Field field = AA.getClass().getDeclaredFeild(“x”);
field.setAccessible(true);
field.get(AA);       如果现在假设我想把AA(3,4)改为AA(3,5);那么我们在获得A类的y字段后在使用上面说的set方法;     [java] view plaincopyprint?Field field = AA.getClass().getFeild(“y”);  
field.set(AA,5);//表示把AA对象的field字段设置为5;  

Field field = AA.getClass().getFeild(“y”);
field.set(AA,5);//表示把AA对象的field字段设置为5;       获得方法的时候就调用Class的Method getMethod(String name,Class<?> parameterTypes)得到名为name参数为parameterType的方法并且会封装为Method类型的对象,在调用Method类的Object invoke(Object obj,Object…args)来执行该方法;
如String s = “abc”;现在假设要实现的是s.charAt(2)的话,下面是代码:
[java] view plaincopyprint?Method m = s.getClass().getMethod(“charAt”,int.class);//获得名为charAt参数为int的方法   
m.invoke(s,2);//对对象s在位置2处执行m方法  

作者: 静等花开    时间: 2012-10-30 19:41
这是以前的笔记,不知道能否帮到你
作者: 毕影彬    时间: 2012-10-30 19:45
毕影彬 发表于 2012-10-30 19:38
你可以用反射知道一个陌生的类中,包含什么方法和属性等等。 而且,反射不只如此,比如后期对于MVC设计中, ...

不好意思,Properties文件,一般是类加载器一起加载进来的。 呵呵,露怯了。;P




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2