码迷,mamicode.com
首页 > 编程语言 > 详细

Java —— Reflect反射机制

时间:2016-04-16 21:14:59      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:

 

  • Class类的使用
    • OOP的世界里,万事万物皆对象。类是谁的对象呢?——类是对象,类是java.lang.Class类的实例对象!There is a class named class.
    • 实例:
    • 技术分享
      //有一个类
      class Foo {
                     void print() {System.out.println("Foo");}  
      }
      
      //在main函数里:
      public static void main(String[] args) {
              //Foo这个类也是一个实例对象,Class类的实例对象,如何表示呢
              
              //任何一个类都是Class类的实例对象,这个实例对象有三种表示方式
              //1. --实际在告诉我们,任何一个类都有一个隐含的静态成员变量-class
              Class c1 = Foo.class;
              
              //2. 已知该类的对象通过getClass 方法
              Foo f1 = new Foo();
              Class c2 = f1.getClass();
              
              //c1, c2表示了Foo类的类类型(class type)
              //指类也是一个对象,是class类的实例对象,这个对象就成为该类的类类型
              
              //不管从c1,c2都代表了Foo类的类类型,一个类只可能是Class类的一个实例对象
              System.out.println(c1 == c2); //true
              
              //3.
              Class c3 = null;
              try {
                  c3 = Class.forName("com.immoc.reflect.Foo");
              } catch (ClassNotFoundException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              }
                  System.out.println(c3 == c2); //true
      
      
              /*
               * 我们可以通过类的类类型创建对象实例;
               * 通过c1 or c2 or c3创建Foo类的对象
               */
              try {
                  Foo foo = (Foo)c1.newInstance(); //需要有无参的构造方法
                  foo.print();
              } catch (InstantiationException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              } catch (IllegalAccessException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              }
          }    
      View Code
    • 动态加载类:例如Class.forName("类的全称")不仅表示了类的类类型,还代表了动态加载类
      • 编译时刻加载类是静态加载类、运行时加载类是动态加载
      • new 对象是静态加载类,在编译时刻就需要加载所有可能使用到的类
      • 动态加载类:
        • Class c = Class.forName(args[0]);
        • OfficeAble oa = (OfficeAble)c.newInstance(); //通过类类型创建该类的对象实例
      • 功能性的类尽量使用动态加载,而非静态加载
    • 基本的数据类型,void关键字 都存在类类型
    • Class类的基本API操作
    • 技术分享
      /**
           * 打印类的信息,包括类的成员函数,成员变量
           * @param obj
           */
          public static void printClassMessage(Object obj) {
              //要获取类的信息,首先要获取类的类类型
              Class c = obj.getClass();//传递的是哪个子类的对象,c就是该类的类类型
              System.out.println("类的名称是:" + c.getName());
              /*
               * Method类,方法对象
               * 一个成员方法就是一个Method对象
               * getMethod()方法获取的是所有public的函数,包括父类继承而来的
               */
              Method[] ms = c.getMethods();
              for(Method m : ms) {
                  //得到方法返回值类型的类类型
                  Class returnType = m.getReturnType();
                  System.out.print(returnType.getName() + " ");
                  System.out.print(m.getName() + "(");
                  //获取参数类型——得到的是参数列表的类型的类类型
                  Class[] paramTypes = m.getParameterTypes();
                  for(Class p : paramTypes) {
                      System.out.print(p.getName() + ",");
                  }
                  System.out.println(")");
              }
          }
      View Code

       

  • 方法的反射
    • 技术分享
      public static void printMethodMessage(Object obj) {
              //要获取类的信息,首先要获取类的类类型
              Class c = obj.getClass();//传递的是哪个子类的对象,c就是该类的类类型
              System.out.println("类的名称是:" + c.getName());
              /*
               * Method类,方法对象
               * 一个成员方法就是一个Method对象
               * getMethod()方法获取的是所有public的函数,包括父类继承而来的
               */
              Method[] ms = c.getMethods();
              for(Method m : ms) {
                  //得到方法返回值类型的类类型
                  Class returnType = m.getReturnType();
                  System.out.print(returnType.getName() + " ");
                  System.out.print(m.getName() + "(");
                  //获取参数类型——得到的是参数列表的类型的类类型
                  Class[] paramTypes = m.getParameterTypes();
                  for(Class p : paramTypes) {
                      System.out.print(p.getName() + ",");
                  }
                  System.out.println(")");
              }
          }
      View Code

       

    • 如何获取某个方法
      • 方法的名称和方法的参数列表才能唯一决定某个方法
    • 方法反射的操作
      • method.invoke(对象,参数列表)
      • 技术分享
        public class MethodDemo1 {
            public static void main(String[] args) {
                /*
                 * 要获取print(int, int)方法
                 * 首先获取类的信息(类的类信息)
                 */
                A a1 = new A();
                Class c = a1.getClass();
                //2. 获取方法,名称和参数列表
                try {
                    Method m = c.getDeclaredMethod("print", new Class[]{int.class, int.class});
                    //方法的反射操作:用对象调用方法
                    m.invoke(a1, new Object[]{10, 20});
                    
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } 
                
            }
        }
        
        class A {
            public void print(int a, int b) {
                System.out.println(a + b);
            }
            public void print(String a, String b) {
                System.out.println(a.toUpperCase() + "," + b.toLowerCase());
            }
        }
        View Code

         

  • 成员变量的反射
    •  成员变量也是对象,java.lang.reflect.Field, Field类封装了关于成员变量的操作
    • getFields()方法获取的是所有的public的成员变量的信息
    • getDeclaredFields()获取的是该类自己声明的所有成员变量的信息
    • 技术分享
      //首先得到类型,然后得到该变量的名称:
      //如:private int t;
      public static void printFieldMessage(Object obj) {
              System.out.println("---------------------------------------------");
              Class c = obj.getClass();
              
              Field[] fs = c.getDeclaredFields();
              for(Field f : fs) {
                  //得到成员变量的类型的类类型 :int
                  Class fieldType = f.getType();
                  String typeName = fieldType.getName();
                  //得到成员变量的名称 :t
                  String fieldName = f.getName();
                  System.out.println("typeName: " + typeName + " fieldName: " + fieldName);
              }
          }
      View Code

       

  • 构造函数的反射
    • 技术分享
      /**
           * 打印构造函数的信息(构造函数也是对象:java.long.Constructor)
           * @param obj
           */
          public static void printConMessage(Object obj) {
              Class c = obj.getClass();
              Constructor[] cs = c.getDeclaredConstructors();
              for(Constructor con : cs) {
                  System.out.print(con.getName() + "(");
                  //获取参数列表
                  Class[] paramTypes = con.getParameterTypes();
                  for(Class cl : paramTypes) {
                      System.out.print(cl.getName() + ",");
                  }
                  System.out.println(")");
              }
          }
      View Code

       

  • Java类加载机制 
  • 通过反射了解集合泛型的本质
    • Java中集合的泛型是防止错误输入的,只在编译阶段有效,编译完之后就无效了。验证:通过方法的反射
    • 技术分享
      public static void main(String[] args) {
              // TODO Auto-generated method stub
              ArrayList l1 = new ArrayList();
              ArrayList<String> l2 = new ArrayList<String>();
              l1.add("hello");
              l1.add(2); //wrong?是跟JDK版本有关系嘛???
              Class c1 = l1.getClass();
              Class c2 = l2.getClass();
              System.out.println(c1 == c2); //true,说明编译之后集合的泛型是去泛型化得
              //反射的操作都是编译之后的操作
              
              try {
                  Method m = c2.getMethod("add", Object.class);
                  m.invoke(l1, "world");
                  System.out.println(l1.size());
              } catch (Exception e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              } 
          }
      View Code

       

应用:通过类的名称来生产一个对象 如:Integer in = (Integer) class.forName(className).newInstance(); 

Java —— Reflect反射机制

标签:

原文地址:http://www.cnblogs.com/little-YTMM/p/5399184.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!