Java中final关键字不像volatile和transient如此神秘,但在程序员心中仍然产生很多疑惑。我经常收到这样的问题,何时将方法声明 为final的,或何时将方法声明为static的,后来我在之前的文章中回复了。这样的问题不是不重要,知道关键字的用法只是掌握该功能的一小部分。类似于现实世界中,一个战士要生存光知道剑能切很多东西是不够的,需要知道如何使用,更重要的是知道如何有效使用。final关键字可以修饰类,方法和变量,对于每一种修饰都有不同的意义,但目的是相同的,保持完整性防止改变。例如,在Java中final类不可以被继承,final变量的值不可以修改,final方法不可以被重载。这给你第一个暗示,Java中何时定义一个方法为final的,明显地是阻止子类修改它的定义,技术上是防止重载。在Java API中有很多的方法表明如何对方法使用final关键字,一个主要的例子是java.lang.Object类,它声明了很多final方法,包括带有 timeout参数的wait方法。另外声明方法为final的是模板方法,它在模板方法设计模式中修饰了算法。因此,你若是不想令子类改变算法,那就定 义为final的来阻止偶然的或恶意的重载。本文你会学到,在Java方法中有效地使用final关键字。
Java中的final方法
我从清理代码中学到的最好的实践是好的设计,而不是列出一些指南。主要例子是clone()方法,其正确的实现依赖于以下一些准则,而不是由系统保证。通 过将Java方法声明为final的,你不仅表明而且保证没有人可以修改。对处理安全和重要函数的敏感方法尤其重要。将方法声明为final的模板方法设计模式是很好的例子。在模板方法设计模式中,方法的声明在一个方法中捕获,但为了增加实现的灵活性提供了hooks。通过使模板方法final,我们要确保是完全按照每个类中定义的算法步骤,但让他们灵活地在自己的方法中定义步骤。顺便提一下,Java中将类声明为final的话,系统会自动保证此类的所有方法都不可以被重载,相当于将这些方法都声明为final的。将一个类声明为final的也是创建不可变类的重要步骤。
这里有一些指导原则,这可以帮助决定何时将方法声明为final的:
1)构造函数调用的方法应该是final的,否则一个子类可以重写和修改方法的行为,这可能会导致意外和不良行为。
2) 考虑将用于性能的关键方法声明为final,这给编译器更多的机会去优化它。编译器可以内联或缓存这些方法,因为他们不能在应用程序的生命周期内改变。虽然现代的JIT甚至能够内联非final方法,但是如果他们认为这会导致性能增益并且不会被重载,那么使用final方法在涉及到JIT之前就可以做内联了。
3)敏感方法,它们的行为是完全的且不可以被重载,应该声明为final。
4)令模板方法final,来使用模板方法设计模式。
总之,将方法声明为final主要是被设计和安全需求所驱动。虽然性能也作为考虑因素之一,但在当今具有先进的JIT的Java世界中不是主要因素。它也是好的想法,为何你将方法声明为final的,这对维护你的代码的开发者有利。还有另外的疑惑是是否将private方法声明为final的。因为private方法不可以被重载,在不能访问它的子类中不可以,在可访问它的内部类中也不可以,因为它们用的是静态绑定。将private方法声明为final的不会提供额外的价值。
原文:http://javarevisited.blogspot.com/2013/12/when-to-make-method-final-in-java.html |