Java反射机制学习总结

来源:互联网 发布:美团众包辅助软件 编辑:程序博客网 时间:2024/05/16 16:15
定义一、能够分析类能力的程序成为反射。(核心卷一定义)
定义二、 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。(网上找的定义义)

反射机制可以用来:
     在运行中分析类的能力。
     在运行中查看对象。
     实现通用的数组操作代码
     利用Method对象,这个对象很想c++中的函数指针。
一、利用反射分析类的能力
     1、反射机制最重要的内容——检查类的结构
          
          sun为我们提供了那些反射机制中的类:

java.lang.Class;                

java.lang.reflect.Constructor; java.lang.reflect.Field;        

java.lang.reflect.Method;

java.lang.reflect.Modifier;
          在java.lang.reflect包中有三个类Field、Method、Constructor分别用于描述类的域、方法和构造器。这三个类都有一个叫做getName的方法,用于返回项目的名称。
     Field类有一个getType方法,用来返回描述域所属类型的Class对象。Method和Constructor类有能够报告参数类型的方法,Method类还有一个可以报告返回类型的方法。这三个类还有一个叫做getModifiers的方法,它将返回一个整型数值,用不同的位开关描述public和static这样的修饰符使用状况。
     Class类中的getField,getMethod和getConstructors方法将分别返回类提供的public域、方法和构造器数组,其中包括超累的公有成员。Class类的getDeclareField、getDeclareMethods和getDeclaredConstructors方法将分别返回类中声明的全部域、方法和构造器,其中包括私有和受保护成员,但不包括超累的成员。

一、Class类的使用

package com.slowly.reflectTest;import java.lang.reflect.Method;class MyFather {      public int fatherMember;      public void methodFather(){           System. out.println( "我是从父类继承而来的方法methodFather" );     }}class Son extends MyFather{      public int sonMemberpublic;      @SuppressWarnings( "unused")      private int sonMemberprivate;      public void methodSon(){           System. out.println( "我是子类自己的方法!" );     }      protected void methodsonProtected(){           System. out.println( "我是子类受保护的方法!!" );     }}public class reflectsample{      public static void main(String[] args) {            try {                 /*                 * 获取c可以有如下两种方法                 * */                 //第一种推荐使用                 Class c = Class.forName( "com.slowly.reflectTest.Son");                 /*第二种不推荐使用                Son son = new Son();                Class c = son.getClass();                */                Son s = (Son) c.newInstance();                System. out.println( "=======调用创建对象的方法=======" );                 s.methodsonProtected();                 s.methodSon();                 s.methodFather();                 //打印加载类的详细信息                System. out.println( "=====加载类的详细信息======" );                System. out.println( c.getName()+ "类自己声明了" +c .getDeclaredFields().length +"个成员变量" );                System. out.println( "类自己公布的方法有" +c .getMethods().length +"个" );           } catch (Exception e) {                 // TODO Auto-generated catch block                 e.printStackTrace();           }     }}

输出结果:



Field类的例子

import java.lang.reflect.*;class Student{      public int age;      private int id;      public boolean gender;      public String name;      public Student( int age, int id, boolean gender,String name){            this. age = age;            this. id = id;            this. gender = gender;            this. name = name;     }}public class Field {      public static void main(String[] args) {           Student tom = new Student(21,1001, true, "Tom");            //获取Student对应的Class类对象            Class c =  tom.getClass();            //获取Student类所有可以访问的成员变量对应的Filed数组           java.lang.reflect.Field[] fieldarray = c.getFields();            //打印Student类对象各成员变量的详细信息           System. out.println( "成员变量名\t\t成员变量类型\t\t成员变量值" );            int size = fieldarray. length;            //循环处理Filed数组            for ( int i = 0; i< size; i++) {                java.lang.reflect.Field tempf = fieldarray[i];                 //打印输出成员变量名称                System. out.print( tempf.getName()+ "\t\t");                 //打印成员变量类型                System. out.print( tempf.getType().toString()                          +( tempf.getType().toString().length()>7? "\t": "\t\t"));                 try {                      //打印成员变量值                     System. out.println( tempf.get( tom));                } catch (IllegalArgumentException | IllegalAccessException e ) {                      // TODO Auto-generated catch block                      e.printStackTrace();                }           }     }}

显示结果:
可以看出,程序打印了正确的成员变量信息,包括age、gender、name成员变量。
而id由于是私有成员,不能在Student类外访问,因此没有打印。

三、Method的介绍及例子


对于invoke()方法有如下几点需要注意
     不管实际对应方法的返回值为什么类型,都作为Object类型返回。若返回为基本数据类型,则返回对应封装类的对象。
     obj参数指出要被调用方法所属的对象,若调用静态的方法用null值。
     args指出要被调用方法的参数序列,若方法没有参数则传递空数组---new Object[0],若方法有基本数据类型的参数则使用基本数据类型的封装对象。
import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;class ForMethod{      //声明静态方法      public static void sayHello(String name){           System. out.println( "你好" +name +"!!!" );     }      public String generateNum( int max, int min){            return (Math. random()*( max- min)+ min)+ "";     }}public class method {      public static void main(String[] args) throws Exception {            //创建ForMethod类对象           ForMethod fm = new ForMethod();            //获取ForMethod类对象对用的Class对象            Class fmc = fm.getClass();            //获取可以访问的对象的对应的Method数组           Method[] md = fmc.getMethods();           System. out.println( "方法名称\t\t返回值类型\t\t参数列表" );            int size = md. length;            for( int i = 0; i< size; i++){                Method tempm = md[ i];                 //打印方法名称                String name = tempm.getName();                System. out.print( name+( name.length()>7? "\t": "\t\t"));                 //打印方法的返回值类型                String returntype = tempm.getReturnType().getName();                System. out.print( returntype+(( returntype.length()>15)? "\t":( returntype.length()>10)? "\t\t": "\t\t\t"));                      //打印方法的参数序列                      Class[] ca = tempm.getParameterTypes();                      int csize = ca. length;                      if( csize==0){                           System. out.println( "没有参数!!" );                     }                      else                      for( int j = 0; j< csize; j++){                          System. out.print( ca[ j].getName()+(( j== csize-1)? "": ","));                     }                      //换行                     System. out.println();           }                     System. out.println( "=====通过反射调用静态方法sayHello======" );                      md[0].invoke( null, new Object[]{ "王强" });                      //通过反射调用非静态方法                     System. out.println( "=====通过反射调用非静态方法generateNum=======" );                     System. out.println( md[1].invoke( fm, new Object[]{new Integer(100),new Integer(1000)}));     }}
输出结果:



四、Constructor类的知识与应用
     Consstructor类的对象代表一个构造器,携带构造器的相关信息,与Field、Method·类类似,其对象也不能通过构造器创建,而是要使用Class对象提供的get()系列方法获得。

例子:

import java.lang.reflect.Constructor;class Student01{     String name;      int age;      //无参构造器      public Student01(){            name = "Tom";            age = 23;     }      //有参构造器      public Student01(String name, int age){            this. name = name;            this. age = age;     }      public void sayHello(){           System. out.println( "您好,我是" +name +"今年" +age +"岁了!" );     }}public class constructor {      public static void main(String[] args) {            try{                 //获取Student类的Class对象                 Class sc = Student01. class;                 //获取可以访问构造器对应的Constructor数组                 Constructor[] ca = sc.getConstructors();                 //对数组进行扫描打印构造器信息                System. out.println( "构造器名\t\t\t\t\t\t参数列表" );                 int size = ca. length;                 //System.out.println(size+"");                 for( int i = 0; i< size; i++){                      Constructor tempc = ca[ i];                      //打印构造器的名字                     String cname = tempc.getName();                     System. out.print( cname+ "\t\t");                      //循环打印构造器的序列参数                      Class[] pm = tempc.getParameterTypes();                      int psize = pm. length;                      if( psize==0){                           System. out.println( "没有参数!" );                     }                      else                      for( int j = 0; j< psize; j++){                          System. out.print( pm[ j].getName()+(( j== psize-1)? "": ","));                     }                      //换行                     System. out.println();                }                 //使用反射调用无参构造器                Student01 stu = (Student01) ca[0].newInstance( new Object[0]);                 //调用创建对象的方法                 stu.sayHello();                 //使用反射调用有参构造器                Student01 stu01 = (Student01) ca[1].newInstance( "王强" ,new Integer(25));                 //调用创建对象的方法                 stu01.sayHello();           } catch(Exception e){                 e.printStackTrace();           }     }}
运行结果:


0 0
原创粉丝点击