`
lganggang131
  • 浏览: 15068 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
最近访客 更多访客>>
社区版块
存档分类
最新评论

java的反射机制(Reflection)

阅读更多

今天复习了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

2
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics