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

  • Java反射的作用?

假如有两个程序员,一个程序员在写程序的时需要使用第二个程序员所写的类,但第二个程序员并没完成他所写的类。那么第一个程序员的代码是不能通过编译的。此时,利用Java反射的机制,就可以让第一个程序员在没有得到第二个程序员所写的类的时候,来完成自身代码的编译。

  • 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();
      }
      }
    • 动态加载类:例如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(")");
      }
      }
  • 方法的反射
    • 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(")");
      }
      }
    • 如何获取某个方法
      • 方法的名称和方法的参数列表才能唯一决定某个方法
    • 方法反射的操作
      • 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());
        }
        }
  • 成员变量的反射
    •  成员变量也是对象,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);
      }
      }
  • 构造函数的反射
    • /**
      * 打印构造函数的信息(构造函数也是对象: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(")");
      }
      }
  • 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();
      }
      }

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

Java —— Reflect反射机制的更多相关文章

  1. Java 类反射机制分析

    Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...

  2. java的反射机制

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

  3. java笔记--反射机制之基础总结与详解

    一.反射之实例化Class类的5种方式: java的数据类型可以分为两类,即引用类型和原始类型(即基本数据类型). 对于每种类型的对象,java虚拟机会实例化不可变的java.lang.Class对象 ...

  4. Java高新技术 反射机制

     Java高新技术 反射机制 知识概要:                   (1)反射的基石 (2)反射 (3)Constructor类 (4)Field类 (5)Method类 (6)用反射方 ...

  5. java的反射机制浅谈(转)

    原文链接:java的反射机制浅谈 一.java的反射机制浅谈 1.何谓反射机制 根据网文,java中的反射机制可以如此定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性 ...

  6. 【转】Java利用反射机制访问私有化构造器

    Java利用反射机制访问私有化构造器 博客分类: java   我们都知道,当一个类的构造方法被设为私有的时候(private),在其他类中是无法用new来实例化一个对象的. 但是有一种方法可以把带有 ...

  7. 【转】java原理—反射机制

    一.什么是反射:反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序语言 ...

  8. java的反射机制(第三篇)

    本文转载自:http://c.biancheng.net/cpp/html/1782.html Person p=new Person();这是什么?当然是实例化一个对象了.可是这种实例化对象的方法存 ...

  9. java原理—反射机制

    http://www.cnblogs.com/forlina/archive/2011/06/21/2085849.html 一.什么是反射:反射的概念是由Smith在1982年首次提出的,主要是指程 ...

随机推荐

  1. python的元组数据类型及常用操作

    Python的元组与列表类似,不同之处在于元组的元素不能修改. 元组使用小括号,列表使用方括号. 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可. 如下实例: tup1 = ('physi ...

  2. thinkphp验证码实现。

    作为我大天朝的程序员,如果不会点thinkphp框架确实有点说不过去了(虽然作为菜鸟的我才入坑没几个月).不过不会也没关系,很简单的一个php框架.今天为大家介绍的是thinkphp如何实现验证码的功 ...

  3. mongo数据库相关目录

    mongodb的docker化安装 mongodb的windows系统下安装 grafana使用Prometheus数据源监控mongo数据库 mongodb副本集的docker化安装 mongodb ...

  4. Spring常见面试题

    本文是通过收集网上各种面试指南题目及答案然后经过整理归纳而来,仅仅是为了方便以后回顾,无意冒犯各位原创作者. Spring框架 1. 什么是Spring? Spring 是个java企业级应用的开源开 ...

  5. 洛谷(P1006 传纸条)

    题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个mm行nn列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运 ...

  6. 【转】在Ubuntu 16.10 Server 上部署 Moodle

    第一步 安装 Ubuntu 16.10 Server LTS Moodle 的官方文档肯定了Ubuntu Server LTS 是适合运维Moodle平台的. 1.使用纯代码交互的服务器Ubuntu更 ...

  7. C++11中rvalue references的使用

    Rvalue references are a feature of C++ that was added with the C++11 standard. The syntax of an rval ...

  8. Hystrix入门指南

    Introduction 1.Where does the name come from? hystrix对应的中文名字是“豪猪”,豪猪周身长满了刺,能保护自己不受天敌的伤害,代表了一种防御机制,这与 ...

  9. 读取Excel错误,未在本地计算机上注册 oledb.4.0

          以前写的一个读取Excel的程序,现在在另外一台机器上运行,竟然报错说"未在本地计算机上注册 oledb.4.0"       最后才知道,原来是因为现在运行的那台电脑 ...

  10. (原)Android到IOS开发的转换(一)

    序)闲扯几句 很早就想入手ios开发,但是一直没有机会,个人没有水果机器,上个公司上班的那台mac mini虽然就在我身边,灰都有一层了,但是一直没有机会开机学习下,因为事多,自上一篇文章后,离职后, ...