Java中反射(Java编程思想第14章--类型信息)整理

        反射允许更加动态的编程风格,类型检测只能在运行时检查,并用异常来报告检测的结果。反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。但是反射机制特别费时,一般是普通操作的1-2个数量级时间。
        JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

Java 语言访问控制检查

        AccessibleObject 类是 Field、Method 和 Constructor 对象的父类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力(阻断虚拟机的访问检查权限 ),则可以通过反射访问private、protected等权限的Field、Method、Constructor。可参考:https://www.cnblogs.com/Java-125/p/8967356.html

public void setAccessible(boolean flag) throws SecurityException 
参数值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。

参数值为 false 则指示反射的对象应该实施 Java 语言访问检查

RTTI和反射的真正区别?

        反射机制并没有什么神奇之处,当通过反射与一个不知道类型的对象打交道时,JVM只是简单的检查这个对象属于哪个特定的类型(就像RTTI一样)。在使用这个对象进行其他操作(如:访问对象的method和域)时,则需要该类Class对象。
        RTTI:只是简单进行了类型检测(利用“(Shape)”方式检查、shape.Instanceof(Shape)检查或通过Class.forName(Shape)获得Class对象(其在RTTI中只是为了用获取的Class对象来检查对象类型是否正确)。编译器在编译时打开和检查.class文件(即:可以用“普通”的方式调用对象的所有方法,如:Object引用.xxxmethod)。
        反射:首先获取Class对象,然后利用Class类提供的一系列方法获取该类的所有信息(method、Fied和Constructor)。类的.class在编译时是不可获取的,只有在运行时打开和检查类的.class文件。该类的.class文件对于JVM来说必须可获取的:要么在本地机器上,要么可以通过网络取得。
反射示例:

Class<?> c = Class.forName(ClassName);//获取class对象;
      Method[] methods = c.getMethods();
      Constructor[] ctors = c.getConstructors();
      if(args.length == 1) {
        for(Method method : methods)
          print(
            p.matcher(method.toString()).replaceAll(""));
        for(Constructor ctor : ctors)
          print(p.matcher(ctor.toString()).replaceAll(""));
        lines = methods.length + ctors.length;
      } else {
        for(Method method : methods)
          if(method.toString().indexOf(args[1]) != -1) {
            print(
              p.matcher(method.toString()).replaceAll(""));
            lines++;
          }
        for(Constructor ctor : ctors)
          if(ctor.toString().indexOf(args[1]) != -1) {
            print(p.matcher(
              ctor.toString()).replaceAll(""));
            lines++;
          }
      }

什么时候需要反射机制?

        如果不知道某个类的确切类型,RTTI可以告诉你,但是在编译时,编译器必须要知道所有通过RTTI来处理的类。
        但是,当身处大规模的编程环境时,就很容易出现:当程序获取一个指向某个并不在你程序空间中对象的引用(从磁盘文件或网络连接上获取了一些字节,这些字节代表一个类),那么你在编译时,你的程序根本无法获知这个对象所属的类。另外,希望提供在跨网络的远程平台上创建和运行对象的能力(被称为“远程方法调用(RMI)”)。
        实际使用场景1 : 用反射机制实现数据库操作DAO,在编写访问数据库时写有很多个表,每个表都有增删改查等操作,如果不使用反射机制就得为不同的表创建不同的DAO类。这样就有开发速度低和代码冗余的缺陷。如果使用java反射机制,只需要写一个DAO类,四个方法–增删改查,传入不同的对象即可。 无需为每一个表都创建DAO类,反射机制会自动帮我们完成剩下的事情,这就是它的好处。该应用场景的示例代码可以参考一下资料:
http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html
http://blog.csdn.net/cuiyaoqiang/article/details/50751612
http://blog.csdn.net/anxin323/article/details/39371059

什么给反射机制提供支持?

        java.lang.reflect类库和Class类一起提供了对反射概念的支持。java.lang.reflect类库中有Methotd、Constructor和Filed类(每个类都实现了Member接口)。这三种类型的对象是由JVM在运行时创建的,表示未知类(有Class.forName(“类的(必须指明路径)完整名称”))里对应的成员。
        使用Class类提供的丰富方法来动态的获取类型的全部信息,详细可以参考JDK,下面列出比较常使用的方法:

  • 获得构造函数的方法 :

    • Constructor getConstructor(Class[] params)//根据指定参数获得public构造器;
    • Constructor[] getConstructors()//获得public的所有构造器;
    • Constructor getDeclaredConstructor(
    • Class[] params)//根据指定参数获得public和非public的构造器;
      Constructor[] getDeclaredConstructors()//获得public的所有构造器 ;
  • 获得类方法的方法:

    • Method getMethod(String name, Class[] params),根据方法名,参数类型获得方法;
    • Method[] getMethods()//获得所有的public方法;
    • Method getDeclaredMethod(String name, Class[] params)//根据方法名和参数类型,获得public和非public的方法
    • Method[] getDeclaredMethods()//获得所以的public和非public方法
  • invokeI()//来调用与Method关联的方法
  • 获得类中属性的方法:
    • Field getField(String name)//根据变量名得到相应的public变量;
    • Field[] getFields()//获得类中所以public的方法;
    • Field getDeclaredField(String name)//根据方法名获得public和非public变量;
    • Field[] getDeclaredFields()//获得类中所有的public和非public方法
              任何方式(如:将接口实现为私有内部类、匿名类等)都无法阻止反射到达并调用和访问类的非public访问权限的方法和域。详情可参见第十四章–14.9接口与参数类型。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值