建议:接口优先于反射机制。

        核心反射机制java.lang.reflect,提供了“通过程序来访问关于已装载的类的信息”的能力。给定一个Class实例,你可以获得Constructor、Method和Fiel实例,分别代表了该Class实例所表示的类的Constructor(构造器)、Method(方法)和Field(域)。这些对象提供了“通过程序来访问类的成员名称、域类型、方法签名等信息”的能力。

        而且,Constructor、Method和Field实例使你能够通过反射机制操作他们的底层对等体:通过调用Constructor、Method和Field实例上的方法,可以构造底层类的实例、调用底层类的方法,并访问底层类的域。例如,Method.invoke使你可以调用任何类的任何对象上的任何方法(遵从常规的安全限制)。反射机制(reflection)允许一个类使用另一个类,即使当前者被编译的时候后者还根本不存在。然而,这种能力也要付出代价:

  • 丧失了编译时类型检查的好处。包括异常检查。如果程序企图用反射方式调用不能存在的或者不可访问的方法,在运行时他将会失败,除非采取了特别的预防措施。
  • 执行反射访问所需要的代码非常笨拙和冗长。编写这样的代码非常乏味,阅读起来也很困难。
  • 性能损失。反射方法调用比普通方法调用慢了许多。具体慢了多少,这很难说,因为受到了多个因素的影响。在我的机器上,速度的差异可能小到2倍,也可能大到50倍。

        核心反射机制最初是为了基于组件的应用创建工具而设计的。这类工具通常要根据需要装载类,并且用反射功能找出他们支持哪些方法和构造器。这些工具允许用户交互式的构建出访问这些类的应用程序,但是所产生出来的这些应用程序能够以正常的方式访问这些类,而不是以反射的方式。反射功能只是在设计时被用到。通常,普通应用程序在运行时不应该以反射方式访问对象。

        有一些复杂的应用程序需要使用反射机制。这些示例中包括浏览器、对象监视器、代码分析工具、解释型的内嵌式系统。在RPC(远程过程调用)系统中使用反射机制也是非常合适的,这样可以不再需要存根编译器。如果你对自己的应用程序是否也属于这一类应用程序而感到怀疑,他很有可能就不属于这一类。

        如果只是以非常有限的形式使用反射机制,虽然也要付出少许代价,但是可以获得许多好处。对于有些程序,他们必须用到在编译时无法获取的类,但是在编译时存在适当的接口或者超类,通过他们可以引用这个类。如果是这种情况,就可以反射方式创建实例,然后通过他们的接口或者超类,以正常的方式访问这些实例。如果适当的构造器不带参数,甚至根本不需要使用java.lang.reflect包;Class.newInstance方法就已经提供了所需的功能。

        类对于在运行时可能不存在的其他类、方法或者域的依赖性,用反射法进行管理,这种做法是合理的,但是很少使用。如果要编写一个包,并且他运行的时候必须依赖其他某个包的多个版本,这种做法可能就非常有用。这种做法就是,在支持包所需要的最小环境对他进行编译,通常是最老的版本,然后以反射方式访问任何更加新的类或者方法。如果企图访问的新类或者新方法在运行时不存在,为了使这汇总方法有效你还必须采取适当的动作。所谓适当的动作,可能包括使用某种其他可替代的办法来达到相同的目的,或者使用简化的功能进行处理。

        简而言之,反射机制是一种功能强大的机制,对于特定的复杂系统编程任务,他是非常必要的,但他也有一些缺点。如果你编写的程序必须要与编译时未知的类一起工作,如有可能,就应该仅仅使用反射机制来实例化对象,而访问对象时则使用编译时已知的某个接口或者超类。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值