使用final关键字真的能提高性能吗?
首先这里有一篇文章:
http://www.javamex.com/tutorials/java_final_performance.shtml
在这篇文章中,作者Neil Coffey说到了下面一些内容:
But to the best of my knowledge, there are no class/method optimisations in Hotspot based on whether or not a class or method is final. In a discussion with members of the Hotspot compiler team back in 2005, they confirmed this was already the case then.
这段话的大致意思是,据作者所知,在Hotspot中没有任何的优化是基于一个类或者一个方法是否是final的。在2005年与Hotspot开发团队的一次讨论中,他们证实了这种情况。
接着作者进行了一个性能测试,测试内容是先有一个基类BaseClass,在基类中定义一个方法A;然后定义三个子类:①ClassA 继承基类②ClassB继承基类并定义为final③classC继承基类,并且被其他类继承;三个子类分别用相同的内容覆写方法A。因为对于每个子类,使用时都有两种方式,例如
BaseClass classA = new ClassA();或
ClassA classA = new ClassA();
因此这里有6种调用方法A的方式,分别对比方法调用的耗时。
结果是:
结果表明,class是否由final修饰不会影响性能,同时第二种声明方法相对更高效,但是第二种有时不符合我们面向接口编程的原则,所以这里存在取舍。
对于final提高性能还有另一种可能,就是编译器倾向于将用final修饰的短方法内联(inline)。文中提到在早期的字节码编译器中错误地采取这种判断内联的方法,而在现代的Java编译器中不再这样。在Hotspot虚拟机中,它的优化是基于JIT技术,而不是基于你是否将方法标记为final。遗憾的是作者并没有对此进行测试,所以这里我们就自己来设计测试。代码如下
public class FinalVsNonFinal
{
private static final int TIMES = 10_0000;
public static void main(String[] args) {
FinalVsNonFinal o = new FinalVsNonFinal();
//多测试几次,看看情况
//输出时间的单位是毫秒
for(int i = 0; i < 4; i++) {
testFinal(o);
testNonFinal(o);
}
}
public final boolean methodA() {
return true;
}
public boolean methodB() {
return true;
}
public static void testFinal(FinalVsNonFinal o) {
long start = System.nanoTime();
for(int i = 0; i < TIMES; i++) {
o.methodA();
}
long duration = System.nanoTime() - start;
System.out.println("Final Method: " + duration/1.0e6);
}
public static void testNonFinal(FinalVsNonFinal o) {
long start = System.nanoTime();
for(int i = 0; i < TIMES; i++) {
o.methodB();
}
long duration = System.nanoTime() - start;
System.out.println("Non-Final Method: " + duration/1.0e6);
}
}
运行结果的截图是:
(我的jdk版本是jdk1.7.0_03,系统是windows 7,cpu是AMD turion RM75)
从上面的截图可以看出,final方法和non-final方法的耗时差不多,但是第1次双方都耗时较多,而后面2次的调用耗时越来越少。在这里,后几次时间的减少就是由于JIT技术,有兴趣的可以去了解下Java中的JIT技术。
综上所述, Java中的final关键字更多是用在设计上,而final关键字本身并不能带来性能的提升。