zoukankan      html  css  js  c++  java
  • java的反射机制

    一、java的反射机制浅谈

    最近研究java研究得很给力,主要以看博文为学习方式。以下是我对java的反射机制所产生的一些感悟,希望各位童鞋看到失误之处不吝指出。受到各位指教之处,如若让小生好好感动,说不定会请各位吃饭哦!

    1.何谓反射机制

    根据网文,java中的反射机制可以如此定义:

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

    2.反射机制如何实现

    谈到反射机制,最诱人的莫过于“动态”二字了。接触过C语言的童鞋们都知道,C语言中也有个和“动态”搭上边的函数:malloc()函数。其实这里的两个动态是一个意思,都指的是非编译时处理,抑或运行时处理。这种机制,可以让程序的弹性增加不少,因为借由此机制,客户可以在程序运行时改变一些他关心的性质:分配内存(当然他可能 完全不知道这么做了),调用某个类(当然他还是被蒙在鼓里)等。

    下面我们就聊聊java中动态机制是如何实现的。

    上一篇文章中提到了java的类的加载问题,但没有更深入地解释其运行机制,在这里就先谈谈这个问题。

    首先不得不提到的是java.lang.Class这个类。

    有这么一段话:

    Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。

    也就是说,ClassLoader找到了需要调用的类时(java为了调控内存的调用消耗,类的加载都在需要时再进行,很抠但是很有效),就会加载它,然后根据.class文件内记载的类信息来产生一个与该类相联系的独一无二的Class对象。该Class对象记载了该类的字段,方法等等信息。以后jvm要产生该类的实例,就是根据内存中存在的该Class类所记载的信息(Class对象应该和我所了解的其他类一样会在堆内存内产生、消亡)来进行。

    而java中的Class类对象是可以人工自然性的(也就是说开放的)得到的(虽然你无法像其他类一样运用构造器来得到它的实例,因为

    Class对象都是jvm产生的。不过话说回来,客户产生的话也是无意义的),而且,更伟大的是,基于这个基础,java实现了反射机制。

    获取Class对象有三种方式:

    1.通过Object类的getClass()方法。例如:

    Class c1 = new String("").getClass();

    2.通过Class类的静态方法——forName()来实现:

    Class c2 = Class.forName("MyObject");

    3.如果T是一个已定义的类型的话,在java中,它的.class文件名:T.class就代表了与其匹配的Class对象,例如:

    Class c3 = Manager.class;

    Class c4 = int.class;

    Class c5 = Double[].class;

    这里需要解释一下3:请记住一句话,java中,一切皆对象。也就是说,基本类型int float 等也会在jvm的内存池像其他类型一样中生成

    一个Class对象。而数组等组合型数据类型也是会生成一个Class对象的,而且更令人惊讶的是,java中数组的本来面目其实就是某个类,惊讶

    中的惊讶是,含有相同元素的相同维数的数组还会共同享用同一个Class对象!其实根据我的臆想,数组的length性质应该就保存在这个Class

    对象里面。

    Class类中存在以下几个重要的方法:

    1.getName()

    一个Class对象描述了一个特定类的特定属性,而这个方法就是返回String形式的该类的简要描述。由于历史原因,对数组的Class对象

    调用该方法会产生奇怪的结果。

    2.newInstance()

    该方法可以根据某个Class对象产生其对应类的实例。需要强调的是,它调用的是此类的默认构造方法。例如:

    MyObject x = new MyObject();

    MyObject y = x.getClass().newInstance();

    3.getClassLoader()

    返回该Class对象对应的类的类加载器。

    4.getComponentType()

    该方法针对数组对象的Class对象,可以得到该数组的组成元素所对应对象的Class对象。例如:

    int[] ints = new int[]{1,2,3};

    Class class1 = ints.getClass();

    Class class2 = class1.getComponentType();

    而这里得到的class2对象所对应的就应该是int这个基本类型的Class对象。

    5.getSuperClass()

    返回某子类所对应的直接父类所对应的Class对象。

    6.isArray()

    判定此Class对象所对应的是否是一个数组对象。

    好啦,现在对Class这个类应该有了一个大致的了解,下面就给出一个反射机制的典型例子供各位分析:

      1 import java.lang.reflect.Array;   
      2 import java.lang.reflect.Constructor;   
      3 import java.lang.reflect.Field;   
      4 import java.lang.reflect.Method;   
      5   
      6 
      7 public class Reflection {   
      8     /**  
      9      * 得到某个对象的公共属性  
     10      *  
     11      * @param owner, fieldName  
     12      * @return 该属性对象  
     13      * @throws Exception  
     14      *  
     15      */  
     16     public Object getProperty(Object owner, String fieldName) throws Exception {   
     17         Class ownerClass = owner.getClass();   
     18   
     19         Field field = ownerClass.getField(fieldName);   
     20   
     21         Object property = field.get(owner);   
     22   
     23         return property;   
     24     }   
     25   
     26     /**  
     27      * 得到某类的静态公共属性  
     28      *  
     29      * @param className   类名  
     30      * @param fieldName   属性名  
     31      * @return 该属性对象  
     32      * @throws Exception  
     33      */  
     34     public Object getStaticProperty(String className, String fieldName)   
     35             throws Exception {   
     36         Class ownerClass = Class.forName(className);   
     37   
     38         Field field = ownerClass.getField(fieldName);   
     39   
     40         Object property = field.get(ownerClass);   
     41   
     42         return property;   
     43     }   
     44   
     45   
     46     /**  
     47      * 执行某对象方法  
     48      *  
     49      * @param owner  
     50      *            对象  
     51      * @param methodName  
     52      *            方法名  
     53      * @param args  
     54      *            参数  
     55      * @return 方法返回值  
     56      * @throws Exception  
     57      */  
     58     public Object invokeMethod(Object owner, String methodName, Object[] args)   
     59             throws Exception {   
     60   
     61         Class ownerClass = owner.getClass();   
     62   
     63         Class[] argsClass = new Class[args.length];   
     64   
     65         for (int i = 0, j = args.length; i < j; i++) {   
     66             argsClass[i] = args[i].getClass();   
     67         }   
     68   
     69         Method method = ownerClass.getMethod(methodName, argsClass);   
     70   
     71         return method.invoke(owner, args);   
     72     }   
     73   
     74   
     75       /**  
     76      * 执行某类的静态方法  
     77      *  
     78      * @param className  
     79      *            类名  
     80      * @param methodName  
     81      *            方法名  
     82      * @param args  
     83      *            参数数组  
     84      * @return 执行方法返回的结果  
     85      * @throws Exception  
     86      */  
     87     public Object invokeStaticMethod(String className, String methodName,   
     88             Object[] args) throws Exception {   
     89         Class ownerClass = Class.forName(className);   
     90   
     91         Class[] argsClass = new Class[args.length];   
     92   
     93         for (int i = 0, j = args.length; i < j; i++) {   
     94             argsClass[i] = args[i].getClass();   
     95         }   
     96   
     97         Method method = ownerClass.getMethod(methodName, argsClass);   
     98   
     99         return method.invoke(null, args);   
    100     }   
    101   
    102   
    103   
    104     /**  
    105      * 新建实例  
    106      *  
    107      * @param className  
    108      *            类名  
    109      * @param args  
    110      *            构造函数的参数  
    111      * @return 新建的实例  
    112      * @throws Exception  
    113      */  
    114     public Object newInstance(String className, Object[] args) throws Exception {   
    115         Class newoneClass = Class.forName(className);   
    116   
    117         Class[] argsClass = new Class[args.length];   
    118   
    119         for (int i = 0, j = args.length; i < j; i++) {   
    120             argsClass[i] = args[i].getClass();   
    121         }   
    122   
    123         Constructor cons = newoneClass.getConstructor(argsClass);   
    124   
    125         return cons.newInstance(args);   
    126   
    127     }   
    128   
    129   
    130        
    131     /**  
    132      * 是不是某个类的实例  
    133      * @param obj 实例  
    134      * @param cls 类  
    135      * @return 如果 obj 是此类的实例,则返回 true  
    136      */  
    137     public boolean isInstance(Object obj, Class cls) {   
    138         return cls.isInstance(obj);   
    139     }   
    140        
    141     /**  
    142      * 得到数组中的某个元素  
    143      * @param array 数组  
    144      * @param index 索引  
    145      * @return 返回指定数组对象中索引组件的值  
    146      */  
    147     public Object getByArray(Object array, int index) {   
    148         return Array.get(array,index);   
    149     }   
    150 }  

    例子的解释就免了,因为读代码加上自己理解是最好的程序员学习方式。另外,此代码来源为互联网。

    好啦,就到这里了。当你知道了java的反射机制后,以后当你接触到java的动态代理时就不会像我一样茫然了。好啦,谢谢围观!

  • 相关阅读:
    SQL性能优化(不断总结)
    字符编码:区位/国标(gb2312、gbk)/机内码/ASCII/ANSI/Big5
    计算机中信息编码
    删除sybase一列报错:The 'select into' database option is not enabled for database.....
    常用Oracle函数(From OTN)
    常用正则
    剖析Windows的消息运行机制 (学习一)
    服务器响应码及解释
    了解注册表结构
    Windows消息大全收藏
  • 原文地址:https://www.cnblogs.com/baobojun/p/4641304.html
Copyright © 2011-2022 走看看