Java基础RTTI与反射之Java

Posted 唐世光

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java基础RTTI与反射之Java相关的知识,希望对你有一定的参考价值。

一、引言 

  很多时候我们的程序可能需要在运行时识别对象和类的信息,比如多态就是基于运行时环境进行动态判断实际引用的对象。在运行时识别对象和类的信息主要有两种方式:1.RTTI,具体是Class对象,它假定我们在编译时已经知道了所有类型。2.反射机制,运行我们在运行时发现和使用类的信息。

二、RTTI

  RTTI(Run-Time Type Infomation),运行时类型信息。可以在运行时识别一个对象的类型。类型信息在运行时通过Class对象表示,Class对象包含与类有关的信息,可以使用Class对象来创建类的实例。

  每个类对应一个Class对象,这个Class对象放在.class文件中,当我们的程序中首次主动使用某类型时,会把该类型所对应的Class对象加载进内存,在这篇文章JVM之类加载器中阐述了哪些情况符合首次主动使用。

  既然RTTI和Class对象有莫大的关系,即有了Class对象,就可以进行很多操作,那么,我们如何获取到Class对象呢?有三种方法1. Class.forName("全限定名");(其中,全限定名为包名+类名)。2. 类字面常量,如String.class,对应String类的Class对象。3.通过getClass()方法获取Class对象,如String str = "abc";str.getClass();。

  通过一个类对应的Class对象后,我们可以做什么?我们可以获取该类的父类、接口、创建该类的对象、该类的构造器、字段、方法等等。总之,威力相当大。

  下面我们通过一个例子来熟悉Class对象的各种用法。

 View Code

  运行结果: 

 View Code

  说明:使用method1、method2、method3三种方法都可以获得Class对象,运行结果是等效的。但是三者还是有稍许的区别。区别是从类的初始化角度来看的。如Class.forName("全限定名")会导致类型的加载、链接、初始化过程,而.class则不会初始化该类。显然,getClass肯定是会初始化该类的,因为这个方法时依托于类的对象。

  下面我们通过一个例子比较.class和forName()两种方法的区别。

 View Code

  运行结果:

 View Code

  说明:从结果也进一步验证了.class不会初始化类,而.forName()会初始化类。并且,对常量静态域的使用也不会导致类的初始化。

三、反射

  与RTTI必须在编译器就知道所有类型不同,反射不必在编译期就知道所有的类型,它可以在运行过程中使用动态加载的类,而这个类不必在编译期就已经知道。反射主要由java.lang.reflect类库的Field、Method、Constructor类支持。这些类的对象都是JVM在运行时进行创建,用来表示未知的类。

  关于两者的区别更深刻表达如下:对于RTTI而言,编译器在编译时打开和检查.class文件;对于反射而言,.class文件在编译时是不可获取的,所以在运行时打开和检查.class文件。

  其实在的第一个例子中我们已经用到了Constructor、Method类,现在我们来更加具体的了解Constructor、Method、Field类。  

 View Code

  输入:boy

  运行结果: 

 View Code

  说明:反射可以让我们创建一个类的实例、在类外部访问类的私有方法、私有字段。反射真的很强大~

四、动态代理-反射的应用

  动态创建代理并且动态处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上。

  下面是动态代理的例子

 View Code

  运行结果: 

 View Code

  说明:可以在invoke方法中进行过滤操作。过滤出以do开头的方法进行转发。

五、总结

  RTTI和反射分析就到此为止,RTTI和反射确实很强大,可以帮助我们干很多事情,用对地方绝对威力无穷,谢谢各位园友的观看~

  

以上是关于Java基础RTTI与反射之Java的主要内容,如果未能解决你的问题,请参考以下文章

Java基础RTTI与反射之Java

13. Java基础之类型信息(RTTI和反射)

Java基础 -- 深入理解Java类型信息(Class对象)与反射机制

RTTI与反射之Java

Java SE基础2:Class类与反射

Java反射以及动态代理(上)