dynamic binding && final method && Class

final 修饰词再对字段进行修饰时:

只对于基本类型以及永恒类才具有常量的意义,原因见: http://www.cnblogs.com/papertigerv5/archive/2012/09/24/2700641.html

 

final修饰符同样可以对类和方法进行修饰。

当某类被final修饰时,表明该类不能作为其他类的基类

  副作用: 由于不能被扩展,也就意味着所有的方法自动成为了final(然而对字段而言没有任何影响)

例子: String是最终类,这样就带来了一个十分确定消息:一个String对象变量必然指向的一个字符串对象,而不能是什么其他的高级字符串什么对象

 

当某类中的某个方法并不希望被扩展类进行覆盖(改写),那么可以声明该方法为final方法.可以保证该方法不被改写。

例子: Calendar本身不是永恒类,然而它的setTime的方法却是被定义为final的。保证了Calendar内部的Date是有自己来确定. 所有的Calendar的扩展类都满足这样的要求。

 

程序员的争论:

   使用final修饰类或者方法,有某些程序员认为必须将除了有多态性的要求的方法以外,都加上final的修饰符来修饰避免方法被覆盖。未有结果。

然而:再使用final修饰符来修饰类或者方法的时候一定要进行仔细的考虑,对于某些父类的某些方法不想在其扩展类中改变语意的那些方法应该被修饰为final

 

final的历史:曾经由于动态绑定的巨大消耗,为了减少该步骤的消耗,如果满足刚刚的父类不想子类改变其方法原义的情况,都需要程序员强制的使用final进行修饰。

对于传统的Java编译器,通过使用final的修饰,不需要额外的动态绑定的寻找方法调用表的消耗,当该方法比较短小,而且调用的频繁,那么编译器很可能采取优化策略:将该方法内联,从而提高效率。(CPU由于有预取下一条指令的能力,所以比较喜欢顺序的执行指令。而如果方法进行内联可以很大的提高CPU的效率)。对于那些没有被声明成为final的方法都无法进行内联方法操作。原因很简单,动态绑定的存在,需要到运行时才能知道具体执行哪个方法。那么编译期做的内联优化就无从谈起。

而对于现在的即时编译器而言,较传统的编译器有更大的优势:其跟踪JVM加载的所有的类,知道当前加载进来的所有类的状况,知道在当前的环境下,哪些类的方法在子类中并没有被覆盖,从而是静态的不需要知道运行时的实际的对象类型。

当然如果有任何一个子类对父类的某方法进行了覆盖,那么父类的对应方法是无法被内联优化的,不过这种情况发生的概率比较低。

posted @ 2012-10-07 21:03  papertiger  阅读(152)  评论(0)    收藏  举报