Java反射机制学习总结

定义一、能够分析类能力的程序成为反射。(核心卷一定义)
定义二、 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。(网上找的定义义)

反射机制可以用来:
     在运行中分析类的能力。
     在运行中查看对象。
     实现通用的数组操作代码
     利用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类的使用

Java反射机制学习总结_第1张图片Java反射机制学习总结_第2张图片

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();
           }
     }
}

输出结果:

Java反射机制学习总结_第3张图片


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类外访问,因此没有打印。
Java反射机制学习总结_第4张图片

三、Method的介绍及例子

Java反射机制学习总结_第5张图片

对于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)}));


     }

}
输出结果:
Java反射机制学习总结_第6张图片

Java反射机制学习总结_第7张图片


2017年5月9号添加

对于上面的问题,是因为

getMethods

public Method[] getMethods() throws SecurityException

返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。

 

返回数组中的元素没有排序,也没有任何特定的顺序。所以第二个图显示,方法的顺序变了,对应的参数也就变了,所以会报错!


可以参考

java反射中getDeclaredMethods和getMethods的区别

四、Constructor类的知识与应用
     Consstructor类的对象代表一个构造器,携带构造器的相关信息,与Field、Method·类类似,其对象也不能通过构造器创建,而是要使用Class对象提供的get()系列方法获得。
Java反射机制学习总结_第8张图片

例子:

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();
           }

     }

}
运行结果:

Java反射机制学习总结_第9张图片

你可能感兴趣的:(javaSE)