黑马程序员——反射1:概述

------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


1.  反射的概念

        反射是Java中一个非常重要的技术。通过反射技术可以在程序运行状态中,获取到任意类(“.class”字节码文件)的所有属性(字段,下同)和方法;而对于任意一个对象,都可以调用它的任意一个方法和属性。因此这种动态(运行时期)获取类的成员(包括构造方法、字段以及方法),以及动态调用该类实例对象成员的技术成为Java语言的反射机制。可以理解为对类的“解剖”。

2.  反射技术的应用背景

        反射技术常见的应用场景包括对现有可独立运行程序功能的扩展。对于已经可以独立运行的Java应用程序来说,由于无法获取它的源代码,因此无法通过修改现有程序的方式进行功能扩展。

        那么通常的做法就是:在程序设计之初,就为后期功能扩展提供了对应的接口。这一接口就是使用“Interface”关键字进行定义的接口。若需要进行功能扩展,只需要定义一个新的类,实现该接口,并按照这一接口定义的规则进行类的描述。最终,把类及其类的信息写入到一个配置文件中,应用程序通过读取这一配置文件获取新类信息,即可创建对象,并调用其方法。那么应用程序就是在读取配置文件的过程中,通过反射技术获取到类的各种成员信息,包括构造方法,字段以及方法。

        实际上,目前常见的Java框架都会用到反射技术,比如,Struct、Spring、Hibernate等等,因此反射技术是我们将来进一步学习JavaEE开发前必须要掌握的一项技术。

 

小知识点1:

        这里我们需要对框架和工具类进行区分。框架就好比是一个毛坯房,如果我们要入住,则需要安装门窗,而若要门窗正常工作,还需要安装锁。那么门窗就好比是自定义类,锁就好比是工具类。毛坯房是由别人(开发商)定义好的,我们向其中安装门窗,实际是毛坯房在调用门窗的功能,这就像是框架在调用自定义类的功能。而向门窗安装锁,就好比是在我们的自定义类中调用工具类的功能,来帮助我们实现自定义功能。

        正像先盖好毛坯房一样,框架是首先被定义出来的,而自定义类是后定义的,也就是说,框架类事先无法得知自定义类的类名的。因此在无法修改框架类源代码的情况下,若想调用后定义的新类的功能,只能通过反射的方式。

 

3.  反射技术的实现细节

3.1  反射技术的实现过程

        反射技术是如何实现上述功能的呢?首先,应用程序通过读取配置文件获取到新类类名,及类的信息。然后根据类名找到用于定义此类的字节码文件,并将这一字节码文件加载进内存,即可获取到该类包括构造方法在内的各种成员信息。进而通过调用构造方法就能创建该类的实例对象。进行以上步骤的代码,通常在编写应用程序时就已经定在了应用程序内,只需在配置文件中写入类名,并对该类按照一定的语法格式进行描述,而不需要再进行其他操作。实际上上述步骤与一般的对象创建过程是一样的,只不过通过另一种形式表现出来而已。大家可以通过下图对反射机制进行进一步了解。


3.2  配置文件

        在上述内容,我们提到新定义的类与应用程序之间的交互是通过一个配置文件完成的。那么配置文件的作用就是用于存储实现某一特定接口的类的类名(包括包名在内的全类名),以及该类的其他信息。应用程序通过读取这一配置文件,获取到该类类名及其信息以后,通过反射技术就能够创建该类的实例对象,并进行对象字段的获取和方法的调用。

        配置文件中除了定义类的相关信息以外,还会定义创建此类对象时所需要的参数。比如,创建ServerSocket对象时,我们需要指定其所监听的端口号,那么在定义配置文件时,就会同时写入指定的端口号——比如“port=10000”,那么应用程序在创建该类实例对象的同时,就会依据配置文件中的参数信息对对象进行初始化操作,令其监听指定的端口。

        其实配置文件的作用与用户输入信息是一样的——配置文件中定义的总是那些程序在运行时不能确定的参数,只不过前者是通过读取配置文件获取信息,后者通过用户输入获取信息。当不确定的是程序操作的对象时,就会在配置文件中定义类及其相关信息。

        实际上,即使程序不对外提供接口,仅利用反射也可以操作一个完全“无关”类的实例对象。但此时,对于配置文件的要求就更高——需要更为详细的对新类进行描述。

4.  反射技术的特点

        通过应用反射技术,“大大”提高了Java程序的扩展性。我们可以与多态进行一个简单的对比。虽然多态也能提高代码的扩展性,但是还是需要创建父类或接口的子类对象才能实现。并且创建子类对象的代码还是需要定义在源代码中才能执行起来。

        那么相比于多态,反射技术首先不需要在代码中创建子类对象。只需要告诉程序,需要添加的新类的类名即可。并且操作新类实例对象的代码不必定义在源代码中(也不能),因为已经在开发应用程序时定义好了这一部分代码。

        现实中反射的应用实例很多,这里我们以Tomcat服务器为例进行说明。正像我们在前面《网络编程》系列博客中曾经提到的那样,Tomcat服务器程序内部就是封装了一个ServerSocket对象,来与客户端Socket对象进行数据传输。而针对不同的客户端,处理请求和应答的方式是不同的。因此Tomcat服务器程序对外提供了一个接口,由开发者根据这一接口定义的规则来实现具体的处理请求和进行应答的方式。

        Tomcat服务器中的上述接口称为“Servlet”,叫做服务器端脚本片段,其实就是一个Java接口。比方说,我们自定义了一个Servlet接口的实现类,称为“MyServlet”,在此类内部定义了某种处理请求和进行应答的方式。然后将类名“MyServlet”写入到“web.xml”配置文件中。当然仅仅写入类名是不够,还需按照xml文件的格式,对该类进行详细的描述,以便程序能够更方便的读取该类的信息。程序通过读取这一配置文件,即可创建此类的实力对象,进而调用其方法。

        通过上述内容可知,通过反射技术实现程序功能的扩展是比较容易的,因为不再需要面对复杂的源代码,只需要通过配置文件与原程序进行“沟通”即可。

        大家可以发现,在应用反射技术进行程序功能扩展时,配置文件起到了一个桥梁的作用。因此,当我们在学习一个新的框架时,首先要了解这一框架的功能,然后就掌握改框架中的配置文件定义方式,第三就要学习框架中常用类方法的使用,最后如果需要还可以了解框架的底层实现原理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值