实战java反射机制-让你迅速认识java强大的反射机制



  • 博客分类: 
  • java
★★★ 本篇为原创,需要引用转载的朋友请注明:《 http://stephen830.iteye.com/blog/256723 》 谢谢支持! ★★★ 


Reflection 是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等等)、superclass(例Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。
 (这句话是引用台湾作家侯捷对反射机制描述的一个概念) 

java的反射机制从java诞生之日起就成为java的一个重要特性。反射机制也是目前众多框架实现的一个基础。 

反射,简单的讲就是根据给出的类的名称,我就可以获得这个类所有的信息(包括属性,构造器,方法等),同时还可以对类的方法进行调用。这在需要动态加载类的情况下尤其显得重要。 

目前流行的大部分java框架(例如ssh等)的底层有很多都是基于反射机制来实现的。 

从下面的实例中可以了解并学会关于java反射的一些基本特点: 
(1)如何获得动态加载类的修饰符,包名,类名,使用的接口,继承的父类 
(2)动态获取类的所有属性名,修饰符,属性类型 
(3)动态获取所有定义的构造器,构造器使用的参数数量和参数类型 
(4)动态获取所有方法,方法的返回值类型,方法名,方法参数数量,方法参数类型 
(5)动态调用加载类的方法
 


下面就从一个例子来深入浅出的认识下java的反射机制: 

Java代码   收藏代码
  1. /* 
  2.  * Created on 2005-6-12 
  3.  * Author stephen 
  4.  * Email zhoujianqiang AT gmail DOT com 
  5.  * CopyRight(C)2005-2008 , All rights reserved. 
  6.  */  
  7. import java.lang.reflect.Constructor;  
  8. import java.lang.reflect.Field;  
  9. import java.lang.reflect.InvocationTargetException;  
  10. import java.lang.reflect.Method;  
  11. import java.lang.reflect.Modifier;  
  12.   
  13. /** 
  14.  * java反射机制的测试类. 
  15.  *  
  16.  * @author stephen 
  17.  * @version 1.0.0 
  18.  */  
  19. public class ReflectTest {  
  20.       
  21.     /** 
  22.      * 数组参数的标志字符和实际对应的类型. 
  23.      * 其中'L'表示对象数组,其余表示java基础类型的数组. 
  24.      */  
  25.     public static final char[]   CODES = new char[]  
  26.     {'Z',      'B',   'C',  'L','D',     'F',    'I',   'J',  'S'};  
  27.     public static final String[] VALUES =            
  28.     {"boolean","byte","char","","double","float","int","long","short"};  
  29.       
  30.     /** 
  31.      * 解析方法的参数. 
  32.      * @param parameter 待解析的参数. 
  33.      * @return 
  34.      */  
  35.     public static String parseParameter(String parameter) {  
  36.         /* 在java.lang.Class类中关于参数的说明补充 
  37.          * ------------------------------------ 
  38.          * Examples: 
  39.          * String.class.getName() 
  40.          *     returns "java.lang.String" 
  41.          * byte.class.getName() 
  42.          *     returns "byte" 
  43.          * (new Object[3]).getClass().getName() 
  44.          *     returns "[Ljava.lang.Object;" 
  45.          * (new int[3][4][5][6][7][8][9]).getClass().getName() 
  46.          *     returns "[[[[[[[I" 
  47.          * ------------------------------------ 
  48.          * 1个[表示1维数组,2个[表示2维数组,...,依此类推。 
  49.          */  
  50.         boolean isArray = false;  
  51.         //如果是数组的可能会在最后带个分号过来,需要去掉.  
  52.         if(parameter.charAt(parameter.length()-1)==';'){  
  53.             //去掉最后的分号  
  54.             parameter = parameter.substring(0,parameter.length()-1);  
  55.         }  
  56.         while(parameter.indexOf('[')==0){  
  57.             isArray = true;  
  58.             parameter = parameter.substring(1)+"[]";  
  59.         }  
  60.         if(isArray){  
  61.             char code = parameter.charAt(0);  
  62.             for(int i=0;i<CODES.length;i++){  
  63.                 if(CODES[i]==code){  
  64.                     parameter=VALUES[i]+parameter.substring(1);  
  65.                     break;  
  66.                 }  
  67.             }  
  68.         }  
  69.         return parameter;  
  70.     }  
  71.       
  72.     /** 
  73.      * 解析属性的类型. 
  74.      * @param parameter 待解析的属性. 
  75.      * @return 
  76.      */  
  77.     public static String parseFieldParameter(String parameter) {  
  78.         return parseParameter(parameter);  
  79.     }  
  80.       
  81.     /** 
  82.      * 解析方法返回值的类型. 
  83.      * @param parameter 待解析的方法返回值类型. 
  84.      * @return 
  85.      */  
  86.     public static String parseMethodParameter(String parameter) {  
  87.         return parseFieldParameter(parameter);  
  88.     }  
  89.       
  90.   
  91.     /** 
  92.      * main方法. 
  93.      * @param args 
  94.      */  
  95.     public static void main(String[] args) {  
  96.         try {  
  97.             StringBuffer debugInfo = new StringBuffer();  
  98.               
  99.             String className = "java.lang.StringBuffer";//填写要测试的类  
  100.             Class c = Class.forName(className);//载入类  
  101.               
  102.             debugInfo.append("****************************************\n");  
  103.             debugInfo.append("*  "+className+" \n*  通过java反射机制取出的信息"+"\n");  
  104.             debugInfo.append("****************************************\n");  
  105.               
  106.             //获取包和类名  
  107.             Package thePackage = c.getPackage();//获取类的包  
  108.             String[] names = c.getName().split("[.]");  
  109.             String name = names[names.length-1];  
  110.             //获取类的修饰符[如 public final private等等],  
  111.             //具体的含义请查看 [java.lang.reflect.Modifier] 中定义的修饰符常量  
  112.             //java.lang.String的修饰符是 public final  
  113.             int modifiers = c.getModifiers();  
  114.             debugInfo.append(Modifier.toString(modifiers)+" class "+ name);  
  115.               
  116.             //取出类的父类(extends)  
  117.             Class superClass = c.getSuperclass();  
  118.             if(superClass!=null && (!"java.lang.Object".equals(superClass.getName()))){  
  119.                 debugInfo.append(" extends ");  
  120.                 debugInfo.append(superClass.getName());  
  121.             }  
  122.               
  123.             //取出类的接口(implements)  
  124.             Class[] interfaces = c.getInterfaces();  
  125.             if(interfaces!=null && interfaces.length>0){  
  126.                 debugInfo.append(" implements ");  
  127.                 for(int i=0;i<interfaces.length;i++){  
  128.                     if(i>0) debugInfo.append(",");  
  129.                     debugInfo.append(interfaces[i].getName());  
  130.                 }  
  131.             }  
  132.               
  133.             debugInfo.append(" {\n");  
  134.               
  135.             //取出所有定义的属性  
  136.             debugInfo.append("    //取出所有定义的属性\n");  
  137.             Field[] fields = c.getDeclaredFields();  
  138.             for(int i=0;fields!=null && i<fields.length;i++){  
  139.                 //取出属性  
  140.                 debugInfo.append("    "+Modifier.toString(fields[i].getModifiers())  
  141.                         +" "+parseFieldParameter(fields[i].getType().getName())  
  142.                         +" "+fields[i].getName());  
  143.                 debugInfo.append(";\n");  
  144.             }  
  145.               
  146.             //获取构造器方法  
  147.             debugInfo.append("    //取出所有的构造器方法\n");  
  148.             Constructor[] constructors = c.getConstructors();//取出所有定义的构造器方法  
  149.             for(int i=0;constructors!=null && i<constructors.length;i++){  
  150.                 //取出构造器  
  151.                 debugInfo.append("    "+Modifier.toString(constructors[i].getModifiers())  
  152.                         +" "+name+"(");  
  153.                 Class[] parameterTypes = constructors[i].getParameterTypes();  
  154.                 for(int j=0;parameterTypes!=null&&j<parameterTypes.length;j++){  
  155.                     if(j>0) debugInfo.append(",");  
  156.                     debugInfo.append(parseParameter(parameterTypes[j].getName()));//构造器参数  
  157.                 }  
  158.                 debugInfo.append("){}\n");  
  159.             }  
  160.               
  161.             //取出构造器以外的所有方法  
  162.             debugInfo.append("    //取出构造器以外的所有方法\n");  
  163.             Method[] methods = c.getDeclaredMethods();  
  164.             for(int i=0;methods!=null && i<methods.length;i++){  
  165.                 //取出方法  
  166.                 debugInfo.append("    "+Modifier.toString(methods[i].getModifiers())+" "  
  167.                         + parseMethodParameter(methods[i].getReturnType().getName()) +" "  
  168.                         +methods[i].getName()+"(");  
  169.                 Class[] parameterTypes = methods[i].getParameterTypes();  
  170.                 for(int j=0;parameterTypes!=null&&j<parameterTypes.length;j++){  
  171.                     if(j>0) debugInfo.append(",");  
  172.                     debugInfo.append(parseParameter(parameterTypes[j].getName()));//构造器参数  
  173.                 }  
  174.                 debugInfo.append("){}\n");  
  175.             }  
  176.             debugInfo.append("}\n");  
  177.               
  178.             System.out.println(debugInfo.toString()+"\n");//输出debug信息  
  179.               
  180.             //利用反射机制来调用类中的方法  
  181.             //创建一个StringBuffer对象实例 相当于 StringBuffer o = new StringBuffer();  
  182.             Object o = c.newInstance();  
  183.             //调用方法 o.append(String):认识当参数为对象类型怎么调用的  
  184.             Class[] paramTypes = {Class.forName("java.lang.String")};//定义append方法需要的参数  
  185.             Object[] values = {new String("hello world")};//定义append方法需要的参数对应的数据  
  186.             //调用append(String)方法 相当于 o.append("hello world");  
  187.             o.getClass().getMethod("append",paramTypes).invoke(o,values);  
  188.             //这里将输出 hello world  
  189.             System.out.println("o.append(\""+values[0]+"\").toString()="+o.toString());  
  190.             //调用方法 o.append(int):认识当参数为int,float,double,char,boolean等基础类型时候怎么调用的  
  191.             paramTypes = new Class[]{int.class};  
  192.             values = new Object[]{new Integer(100)};  
  193.             o.getClass().getMethod("append",paramTypes).invoke(o,values);  
  194.             //这里将输出 hello world100  
  195.             System.out.println("o.append(\""+values[0]+"\").toString()="+o.toString());  
  196.               
  197.               
  198.         } catch (ClassNotFoundException e) {  
  199.             e.printStackTrace();  
  200.         } catch (SecurityException e) {  
  201.             e.printStackTrace();  
  202.         } catch (NoSuchMethodException e) {  
  203.             e.printStackTrace();  
  204.         } catch (InstantiationException e) {  
  205.             e.printStackTrace();  
  206.         } catch (IllegalAccessException e) {  
  207.             e.printStackTrace();  
  208.         } catch (IllegalArgumentException e) {  
  209.             e.printStackTrace();  
  210.         } catch (InvocationTargetException e) {  
  211.             e.printStackTrace();  
  212.         }  
  213.     }  
  214. }  


除了例子中给出的一些用法,其实通过java反射还可以进行更多的事情,有兴趣的朋友可以自己再深入研究下。 

如果你要更好的理解一些框架(例如ssh等)的结构,那么你更加需要好好的研究下这个反射机制。 




  • 博客分类: 
  • java
★★★ 本篇为原创,需要引用转载的朋友请注明:《 http://stephen830.iteye.com/blog/256723 》 谢谢支持! ★★★ 


Reflection 是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等等)、superclass(例Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。
 (这句话是引用台湾作家侯捷对反射机制描述的一个概念) 

java的反射机制从java诞生之日起就成为java的一个重要特性。反射机制也是目前众多框架实现的一个基础。 

反射,简单的讲就是根据给出的类的名称,我就可以获得这个类所有的信息(包括属性,构造器,方法等),同时还可以对类的方法进行调用。这在需要动态加载类的情况下尤其显得重要。 

目前流行的大部分java框架(例如ssh等)的底层有很多都是基于反射机制来实现的。 

从下面的实例中可以了解并学会关于java反射的一些基本特点: 
(1)如何获得动态加载类的修饰符,包名,类名,使用的接口,继承的父类 
(2)动态获取类的所有属性名,修饰符,属性类型 
(3)动态获取所有定义的构造器,构造器使用的参数数量和参数类型 
(4)动态获取所有方法,方法的返回值类型,方法名,方法参数数量,方法参数类型 
(5)动态调用加载类的方法
 


下面就从一个例子来深入浅出的认识下java的反射机制: 

Java代码   收藏代码
  1. /* 
  2.  * Created on 2005-6-12 
  3.  * Author stephen 
  4.  * Email zhoujianqiang AT gmail DOT com 
  5.  * CopyRight(C)2005-2008 , All rights reserved. 
  6.  */  
  7. import java.lang.reflect.Constructor;  
  8. import java.lang.reflect.Field;  
  9. import java.lang.reflect.InvocationTargetException;  
  10. import java.lang.reflect.Method;  
  11. import java.lang.reflect.Modifier;  
  12.   
  13. /** 
  14.  * java反射机制的测试类. 
  15.  *  
  16.  * @author stephen 
  17.  * @version 1.0.0 
  18.  */  
  19. public class ReflectTest {  
  20.       
  21.     /** 
  22.      * 数组参数的标志字符和实际对应的类型. 
  23.      * 其中'L'表示对象数组,其余表示java基础类型的数组. 
  24.      */  
  25.     public static final char[]   CODES = new char[]  
  26.     {'Z',      'B',   'C',  'L','D',     'F',    'I',   'J',  'S'};  
  27.     public static final String[] VALUES =            
  28.     {"boolean","byte","char","","double","float","int","long","short"};  
  29.       
  30.     /** 
  31.      * 解析方法的参数. 
  32.      * @param parameter 待解析的参数. 
  33.      * @return 
  34.      */  
  35.     public static String parseParameter(String parameter) {  
  36.         /* 在java.lang.Class类中关于参数的说明补充 
  37.          * ------------------------------------ 
  38.          * Examples: 
  39.          * String.class.getName() 
  40.          *     returns "java.lang.String" 
  41.          * byte.class.getName() 
  42.          *     returns "byte" 
  43.          * (new Object[3]).getClass().getName() 
  44.          *     returns "[Ljava.lang.Object;" 
  45.          * (new int[3][4][5][6][7][8][9]).getClass().getName() 
  46.          *     returns "[[[[[[[I" 
  47.          * ------------------------------------ 
  48.          * 1个[表示1维数组,2个[表示2维数组,...,依此类推。 
  49.          */  
  50.         boolean isArray = false;  
  51.         //如果是数组的可能会在最后带个分号过来,需要去掉.  
  52.         if(parameter.charAt(parameter.length()-1)==';'){  
  53.             //去掉最后的分号  
  54.             parameter = parameter.substring(0,parameter.length()-1);  
  55.         }  
  56.         while(parameter.indexOf('[')==0){  
  57.             isArray = true;  
  58.             parameter = parameter.substring(1)+"[]";  
  59.         }  
  60.         if(isArray){  
  61.             char code = parameter.charAt(0);  
  62.             for(int i=0;i<CODES.length;i++){  
  63.                 if(CODES[i]==code){  
  64.                     parameter=VALUES[i]+parameter.substring(1);  
  65.                     break;  
  66.                 }  
  67.             }  
  68.         }  
  69.         return parameter;  
  70.     }  
  71.       
  72.     /** 
  73.      * 解析属性的类型. 
  74.      * @param parameter 待解析的属性. 
  75.      * @return 
  76.      */  
  77.     public static String parseFieldParameter(String parameter) {  
  78.         return parseParameter(parameter);  
  79.     }  
  80.       
  81.     /** 
  82.      * 解析方法返回值的类型. 
  83.      * @param parameter 待解析的方法返回值类型. 
  84.      * @return 
  85.      */  
  86.     public static String parseMethodParameter(String parameter) {  
  87.         return parseFieldParameter(parameter);  
  88.     }  
  89.       
  90.   
  91.     /** 
  92.      * main方法. 
  93.      * @param args 
  94.      */  
  95.     public static void main(String[] args) {  
  96.         try {  
  97.             StringBuffer debugInfo = new StringBuffer();  
  98.               
  99.             String className = "java.lang.StringBuffer";//填写要测试的类  
  100.             Class c = Class.forName(className);//载入类  
  101.               
  102.             debugInfo.append("****************************************\n");  
  103.             debugInfo.append("*  "+className+" \n*  通过java反射机制取出的信息"+"\n");  
  104.             debugInfo.append("****************************************\n");  
  105.               
  106.             //获取包和类名  
  107.             Package thePackage = c.getPackage();//获取类的包  
  108.             String[] names = c.getName().split("[.]");  
  109.             String name = names[names.length-1];  
  110.             //获取类的修饰符[如 public final private等等],  
  111.             //具体的含义请查看 [java.lang.reflect.Modifier] 中定义的修饰符常量  
  112.             //java.lang.String的修饰符是 public final  
  113.             int modifiers = c.getModifiers();  
  114.             debugInfo.append(Modifier.toString(modifiers)+" class "+ name);  
  115.               
  116.             //取出类的父类(extends)  
  117.             Class superClass = c.getSuperclass();  
  118.             if(superClass!=null && (!"java.lang.Object".equals(superClass.getName()))){  
  119.                 debugInfo.append(" extends ");  
  120.                 debugInfo.append(superClass.getName());  
  121.             }  
  122.               
  123.             //取出类的接口(implements)  
  124.             Class[] interfaces = c.getInterfaces();  
  125.             if(interfaces!=null && interfaces.length>0){  
  126.                 debugInfo.append(" implements ");  
  127.                 for(int i=0;i<interfaces.length;i++){  
  128.                     if(i>0) debugInfo.append(",");  
  129.                     debugInfo.append(interfaces[i].getName());  
  130.                 }  
  131.             }  
  132.               
  133.             debugInfo.append(" {\n");  
  134.               
  135.             //取出所有定义的属性  
  136.             debugInfo.append("    //取出所有定义的属性\n");  
  137.             Field[] fields = c.getDeclaredFields();  
  138.             for(int i=0;fields!=null && i<fields.length;i++){  
  139.                 //取出属性  
  140.                 debugInfo.append("    "+Modifier.toString(fields[i].getModifiers())  
  141.                         +" "+parseFieldParameter(fields[i].getType().getName())  
  142.                         +" "+fields[i].getName());  
  143.                 debugInfo.append(";\n");  
  144.             }  
  145.               
  146.             //获取构造器方法  
  147.             debugInfo.append("    //取出所有的构造器方法\n");  
  148.             Constructor[] constructors = c.getConstructors();//取出所有定义的构造器方法  
  149.             for(int i=0;constructors!=null && i<constructors.length;i++){  
  150.                 //取出构造器  
  151.                 debugInfo.append("    "+Modifier.toString(constructors[i].getModifiers())  
  152.                         +" "+name+"(");  
  153.                 Class[] parameterTypes = constructors[i].getParameterTypes();  
  154.                 for(int j=0;parameterTypes!=null&&j<parameterTypes.length;j++){  
  155.                     if(j>0) debugInfo.append(",");  
  156.                     debugInfo.append(parseParameter(parameterTypes[j].getName()));//构造器参数  
  157.                 }  
  158.                 debugInfo.append("){}\n");  
  159.             }  
  160.               
  161.             //取出构造器以外的所有方法  
  162.             debugInfo.append("    //取出构造器以外的所有方法\n");  
  163.             Method[] methods = c.getDeclaredMethods();  
  164.             for(int i=0;methods!=null && i<methods.length;i++){  
  165.                 //取出方法  
  166.                 debugInfo.append("    "+Modifier.toString(methods[i].getModifiers())+" "  
  167.                         + parseMethodParameter(methods[i].getReturnType().getName()) +" "  
  168.                         +methods[i].getName()+"(");  
  169.                 Class[] parameterTypes = methods[i].getParameterTypes();  
  170.                 for(int j=0;parameterTypes!=null&&j<parameterTypes.length;j++){  
  171.                     if(j>0) debugInfo.append(",");  
  172.                     debugInfo.append(parseParameter(parameterTypes[j].getName()));//构造器参数  
  173.                 }  
  174.                 debugInfo.append("){}\n");  
  175.             }  
  176.             debugInfo.append("}\n");  
  177.               
  178.             System.out.println(debugInfo.toString()+"\n");//输出debug信息  
  179.               
  180.             //利用反射机制来调用类中的方法  
  181.             //创建一个StringBuffer对象实例 相当于 StringBuffer o = new StringBuffer();  
  182.             Object o = c.newInstance();  
  183.             //调用方法 o.append(String):认识当参数为对象类型怎么调用的  
  184.             Class[] paramTypes = {Class.forName("java.lang.String")};//定义append方法需要的参数  
  185.             Object[] values = {new String("hello world")};//定义append方法需要的参数对应的数据  
  186.             //调用append(String)方法 相当于 o.append("hello world");  
  187.             o.getClass().getMethod("append",paramTypes).invoke(o,values);  
  188.             //这里将输出 hello world  
  189.             System.out.println("o.append(\""+values[0]+"\").toString()="+o.toString());  
  190.             //调用方法 o.append(int):认识当参数为int,float,double,char,boolean等基础类型时候怎么调用的  
  191.             paramTypes = new Class[]{int.class};  
  192.             values = new Object[]{new Integer(100)};  
  193.             o.getClass().getMethod("append",paramTypes).invoke(o,values);  
  194.             //这里将输出 hello world100  
  195.             System.out.println("o.append(\""+values[0]+"\").toString()="+o.toString());  
  196.               
  197.               
  198.         } catch (ClassNotFoundException e) {  
  199.             e.printStackTrace();  
  200.         } catch (SecurityException e) {  
  201.             e.printStackTrace();  
  202.         } catch (NoSuchMethodException e) {  
  203.             e.printStackTrace();  
  204.         } catch (InstantiationException e) {  
  205.             e.printStackTrace();  
  206.         } catch (IllegalAccessException e) {  
  207.             e.printStackTrace();  
  208.         } catch (IllegalArgumentException e) {  
  209.             e.printStackTrace();  
  210.         } catch (InvocationTargetException e) {  
  211.             e.printStackTrace();  
  212.         }  
  213.     }  
  214. }  


除了例子中给出的一些用法,其实通过java反射还可以进行更多的事情,有兴趣的朋友可以自己再深入研究下。 

如果你要更好的理解一些框架(例如ssh等)的结构,那么你更加需要好好的研究下这个反射机制。 

附录:你可以下载本篇使用的例子 ReflectTest.zip 



------------------------------------------------------------- 
分享知识 分享快乐,分享知识,分享快乐,希望文章能给需要的朋友带来小小的帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值