菏泽美丽的风景

认真做好每一件事,开开心心过完每一天

Java反射机制初探
Java反射机制初探
2人收藏此文章, 我要收藏发表于8个月前(2012-04-24 11:52) , 已有70次阅读 ,共0个评论

反射,reflection,听其名就像照镜子一样,可以看见自己也可以看见别人的每一部分。在java语言中这是一个很重要的特性。下面是来自sun公司官网关于反射的介绍:

Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members and display them.

The ability to examine and manipulate a Java class from within itself may not sound like very much, but in other programming languages this feature simply doesn't exist. For example, there is no way in a Pascal, C, or C++ program to obtain information about the functions defined within that program.

One tangible use of reflection is in JavaBeans, where software components can be manipulated visually via a builder tool. The tool uses reflection to obtain the properties of Java components (classes) as they are dynamically loaded.

那么解释一下就是,反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个java的类获取他所有的成员变量和方法并且显示出来。这个能特定我们不常看到,但是在其他的比如C或者C++语言中很不就存在这个特性。一个常见的例子是在JavaBean中,一些组件可以通过一个构造器来操作。这个构造器就是用的反射在动态加载的时候来获取的java中类的属性的。

反射的前传:类类型 Class Class

java中有一个类很特殊,就是Class类,很多朋友在写程序的时候有用过比如Apple.class来查看类型信息,大家就可以把它理解为封装了类的信息,很多解释说Class类没有构造器,其实是有的,只不过它的构造方法是private的(构造函数还有private的??有,这样是为了禁止开发者去自己创建Class类的实例)。我们可以看一下JDK中源码:

注释很明确的告诉了我们,这个类是有JVM来创建的,所以我们就不用麻烦了。如果我们拿到一个类的类型信息,就可以利用反射获取其各种成员以及方法了。(注:Class 从JDK1.5版本后就开始更多为泛型服务了)那么我们怎么拿到一个类型的信息呢?假设我们有一个Role类:

01 /**  
02           * 获取构造方法Constructor  
03           * getConstructor()  only for public   
04           * getDeclaredConstructor()  global access all   
05           *   
06           * */ 
07              
08          //指定参数列表获取特定的方法  
09          Constructor con = cls1.getDeclaredConstructor(new Class[]{String.class});  
10          con.setAccessible(true); //设置可访问的权限  
11          Object obj = con.newInstance(new Object[]{"liyang"});  
12          System.out.println(obj);  //打印一下这个对象的信息  
13              
14  //获取所有的构造方法集合  
15          Constructor con1[] = cls1.getDeclaredConstructors();  
16          con1[1].setAccessible(true);  
17          Object obj1 = con1[1].newInstance(new Object[]{"tom"});  
18          System.out.println(obj1);
01 package yui;  
02      
03  /**  
04   * A base class having some attributes and methods  
05   * <A class=referer href="http://my.oschina.net/arthor" target=_blank>@author</A>  Octobershiner  
06   * <A class=referer href="http://my.oschina.net/u/266547" target=_blank>@since</A>  2012 3 17  
07   *   
08   * */ 
09  publicclass Role {  
10          
11      privateString name;  
12      privateString type;  
 
1 //获得类类型的两种方式  
2         Class cls1 = Role.class;  
3         Class cls2 = Class.forName("yui.Role");

注意第二种方式中,forName中的参数一定是完整的类名(包名+类名),并且这个方法需要捕获异常。现在得到cls1就可以创建一个Role类的实例了,利用Class的newInstance方法相当于调用类的默认的构造器

1 Object o = cls1.newInstance(); //创建一个实例  
2         //Object o1 = new Role();   //与上面的方法等价

这样就创建了一个对象,缺点是我们只能利用默认构造函数,因为Class的newInstance是不接受参数的,后面会讲到可接受参数的newInstance,第二,如果类的构造函数是private的,比如Class,我们仍旧不能实例化其对象。

获取类的构造器

首先介绍一下Constructor类,这个类用来封装反射得到的构造器,Class有四个方法来获得Constructor对象

  • public Constructor<?>[] getConstructors()      返回类中所有的public构造器集合,默认构造器的下标为0
  • public Constructor<T> getConstructor(Class<?>... parameterTypes)   返回指定public构造器,参数为构造器参数类型集合
  • public Constructor<?>[] getDeclaredConstructors()  返回类中所有的构造器,包括私有
  • public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回任意指定的构造器

从名字来看,还是很好懂的,带上Declared的都是获得所有的构造方法,包括私有,哈,这下我们就可以调用原本不允许调用的私有构造器了,看代码

01 /**  
02           * 获取构造方法Constructor  
03           * getConstructor()  only for public   
04           * getDeclaredConstructor()  global access all   
05           *   
06           * */ 
07              
08          //指定参数列表获取特定的方法  
09          Constructor con = cls1.getDeclaredConstructor(newClass[]{String.class});  
10          con.setAccessible(true);//设置可访问的权限  
11          Object obj = con.newInstance(newObject[]{"liyang"});  
12          System.out.println(obj); //打印一下这个对象的信息  
13              
14  //获取所有的构造方法集合  
15          Constructor con1[] = cls1.getDeclaredConstructors();  
16          con1[1].setAccessible(true);  
17          Object obj1 = con1[1].newInstance(newObject[]{"tom"});  
18          System.out.println(obj1);

解释一下:第一个是获得一个指定的方法,我们指定了参数是一个String类型,第二段我们获得了所有的构造方法集合,并选取了其中一个创建了新的对象。注意这里Constructor的newInstance方法就可以设置参数了,与文章前面的同样的方法形成了对比。

注意,以上的四个方法全部需要抛出异常,当我们获得私有的方法的时候,要用setAccessible设置一下可访问的权限,例子中没有演示获取共有方法,那个比较简单,就不做介绍了,其实掌握了上面两个,其他就好理解了。

获取类的成员变量

了解了构造器,其实你可以猜到成员变量的获取方法了,成员变量用Field类进行封装。

主要的方法非常的类似:

  • public Field getDeclaredField(String name)  获取任意指定名字的成员
  • public Field[] getDeclaredFields()             获取所有的成员变量
  • public Field getField(String name)           获取任意public成员变量
  • public Field[] getFields()                          获取所有的public成员变量

可以看出这些方法都是异曲同工的,好了直接看一下例子吧

1 /**  
2           * 获取成员变量Field  
3           * getField()  
4           * getDeclaredField()  
5           * */ 
6          Field mem = cls1.getDeclaredField("name");  
7          mem.setAccessible(true);        
8          System.out.println("we get form field :"+mem.get(obj));

这是在访问私有变量,什么私有变量也可以访问??是的。。。。

获取类的方法

我觉得你已经可以帮我写这一段了,封装类的方法的类是Method.获取method也有四个方法,猜到了没??

  • public Method[] getMethods()    获取所有的共有方法的集合
  • public Method getMethod(String name,Class<?>... parameterTypes) 获取指定公有方法 参数1:方法名 参数2:参数类型集合  
  • public Method[] getDeclaredMethods()  获取所有的方法
  • public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 获取任意指定方法

看下面的例子吧

1 /**  
2           * 调用类的方法 Method  
3           * getMethod()  
4           * getDeclaredMethod()  
5           *   
6           * */ 
7          Method f = cls1.getMethod("getName",null);  
8          Object name = f.invoke(obj,null);  
9          System.out.println("we invoke method : "+ name);

这个很简单吧,无参的时候我们只要传null就行了。

总  结:

以上就是反射机制的简单的使用,显然学过spring的朋友一定明白了,为什么可以通过配置文件就可以让我们获得指定的方法和变量,在我们创建对象的时候都是通过传进string实现的,就好像你需要什么,我们去为你生产,还有我们一直在用Object,这就说明java语言的动态特性,依赖性大大的降低了。

阅读更多
想对作者说点什么? 我来说一句

Java反射机制 Java反射机制

2008年12月28日 20KB 下载

Java反射机制

2011年10月10日 188KB 下载

java反射机制与动态代理

2010年03月28日 250KB 下载

Java反射机制课件ppt

2010年06月28日 268KB 下载

JAVA 反射机制应用

2008年10月17日 124KB 下载

java反射机制教程

2009年07月24日 202KB 下载

java反射原理

2011年07月04日 450KB 下载

没有更多推荐了,返回首页

不良信息举报

Java反射机制初探

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭