最近和一位师兄交流了一下Java,真可谓是大有收获,让我好好的学习了一下javad的反射机制,同终于明白了spring等框架的一个基本实现的思想,那么今天就和大家分享一下java的反射机制。

  反射,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类:

 1 package yui;
2
3 /**
4 * A base class having some attributes and methods
5 * @author Octobershiner
6 * @since 2012 3 17
7 *
8 * */
10 public class Role {
11
12 private String name;
13 private String type;
14
15 // Constructors
16 public Role(){
17 System.out.println("Constructor Role() is invoking");
18 }
19 //私有构造器
20 private Role(String name){
21 this.name = name;
22 System.out.println("Constructor Role(String name) is invoking.");
23 }
24
25 //get and set method
26
27 public String getName() {
28 return name;
29 }
30 public void setName(String name) {
31 this.name = name;
32 }
33 public String getType() {
34 return type;
35 }
36 public void setType(String type) {
37 this.type = type;
38 }
39
40 //override the toString method to show the class
41 @Override
42 public String toString(){
43 return "This is a role called "+this.name;
44 }
45
46 }

  在没有对象实例的时候,主要有两种办法。

        //获得类类型的两种方式
Class cls1 = Role.class;
Class cls2 = Class.forName("yui.Role");

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

        Object o = cls1.newInstance(); //创建一个实例
//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的都是获得所有的构造方法,包括私有,哈,这下我们就可以调用原本不允许调用的私有构造器了,看代码
 
 1         /**
2 * 获取构造方法Constructor
3 * getConstructor() only for public
4 * getDeclaredConstructor() global access all
5 *
6 * */
7
8 //指定参数列表获取特定的方法
9 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);
  
  解释一下:第一个是获得一个指定的方法,我们指定了参数是一个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));
9
  
  这是在访问私有变量,什么私有变量也可以访问??是的。。。。
     
     
获取类的方法                                                                                                                                                                      
     
   我觉得你已经可以帮我写这一段了,封装类的方法的类是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反射机制初探的更多相关文章

  1. Java 反射机制 初探*

    反射机制初探 * 走进沼泽 在正常的程序中,先有类,然后再有对象. 取得Class对象(类对象) public final Class<?> getClass() ; 实例观察: publ ...

  2. java反射机制初探

    最近和一位师兄交流了一下Java,真可谓是大有收获,让我好好的学习了一下javad的反射机制,同终于明白了spring等框架的一个基本实现的思想,那么今天就和大家分享一下java的反射机制. 反射,r ...

  3. 初探Java反射机制

    反射库提供了一个非常丰富且精心设计的工具集,以便编写能够动态操纵java代码的程序库.这项功能被大量地应用于JavaBeans中.反射机制提供了在运行状态中获得和调用修改任何一个类的属性和方法的能力. ...

  4. Java反射机制详解(3) -java的反射和代理实现IOC模式 模拟spring

    IOC(Inverse of Control) 可翻译为“控制反转”,但大多数人都习惯将它称为“依赖注入”.在Spring中,通过IOC可以将实现类.参数信息等配置在其对应的配置文件中,那么当 需要更 ...

  5. 浅谈java反射机制

    目录 什么是反射 初探 初始化 类 构造函数 属性 方法 总结 思考 什么是反射 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意 ...

  6. 第28章 java反射机制

    java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...

  7. Java反射机制

    Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射:     静态编译:在编译时确定类型,绑定对象,即通过 ...

  8. java基础知识(十一)java反射机制(上)

    java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...

  9. java基础知识(十一)java反射机制(下)

    1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...

随机推荐

  1. [转]C++学习心得

    1.把C++当成一门新的语言学习: 2.看<Thinking In C++>: 3.看<The C++ Programming Language>和<Inside The ...

  2. Java如何获取当前的jar包路径以及如何读取jar包中的资源

    写作业的时候要输出一个record.dat文件到jar包的同级目录,但是不知道怎么定位jar包的路径.百度到的方法不很靠谱,所以在这里记录一下. 一:使用类路径 String path = this. ...

  3. dwz笔记之tree权限扩展

    碰到的问题:tree选择子节点时,父级节点的值没有选择 解决方法如下(红色部分): 原代码: _checkParent:function(){ if($(this).parent().hasClass ...

  4. [Mugeda HTML5技术教程之14]案例分析:制作网页游戏

    本文档要分析的案例是一个爱消除的网页小游戏,从中可以体会一些Mugeda API的用法和使用Mugeda动画制作网页游戏的方法. (一)游戏规则: 1.开始游戏时,手机出现在最上面一行的任意一格: 2 ...

  5. ubuntu12.04 安装 ruby1.9.3

    sudo apt-add-repository ppa:brightbox/ruby-ng sudo apt-get update sudo apt-get install ruby rubygems ...

  6. shopnc怎么开启伪静态 shopnc开启伪静态的方法

    最近要给一个shopnc网站开启伪静态,用的是shopnc b2b2c,在网上搜索了好多shopnc开启伪静态的方法,但都是针对shaopnc c2c的,没有关于shopnc b2b2c的,最后终于找 ...

  7. 灯塔(LightHouse)

    Description As shown in the following figure, If another lighthouse is in gray area, they can beacon ...

  8. 数据结构之------C++指针冒泡排序算法

    C++通过指针实现一位数组的冒泡排序算法. 冒泡排序 冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法. 代码: /* Name:冒泡排序算法 Copyright:Null ...

  9. 采购术语PR、PO、RFQ、RFI、SOW、BOM、JIT、VMI、MRO 是什么意思

    PO:Purchase Order Form 采购订单,公司对外使用,还有个PR: ,公司内部使用的采购申请单 PR (Purchase Requirent) 请购单,采购申请单,代表企业内部的申请需 ...

  10. C语言---类型转换

    itoa 功 能:把一整数转换为字符串 用 法:char *itoa(int value, char *string, int radix); 详细解释:itoa是英文integer to array ...