本文翻译自:Does use of final keyword in Java improve the performance?

In Java we see lots of places where the final keyword can be used but its use is uncommon. 在Java中,我们看到很多可以使用final关键字的地方,但它的使用并不常见。

For example: 例如:

String str = "abc";
System.out.println(str);

In the above case, str can be final but this is commonly left off. 在上面的例子中, str可以是final但通常不会这样。

When a method is never going to be overridden we can use final keyword. 当一个方法永远不会被覆盖时,我们可以使用final关键字。 Similarly in case of a class which is not going to be inherited. 类似地,如果一个类不会被继承。

Does the use of final keyword in any or all of these cases really improve performance? 在任何或所有这些案例中使用final关键字是否真的能提高性能? If so, then how? 如果是这样,那怎么样? Please explain. 请解释。 If the proper use of final really matters for performance, what habits should a Java programmer develop to make best use of the keyword? 如果正确使用final对性能有用,那么Java程序员应该养成哪些习惯来充分利用关键字?


#1楼

参考:https://stackoom.com/question/HxGu/在Java中使用final关键字可以提高性能吗


#2楼

final keyword can be used in five ways in Java. final关键字可以在Java中以五种方式使用。

  1. A class is final 课程是最终的
  2. A reference variable is final 参考变量是最终的
  3. A local variable is final 局部变量是最终的
  4. A method is final 方法是最终的

A class is final: a class is final means we cannot be extended or inheritance means inheritance is not possible. 一个类是final:一个类是final意味着我们不能被扩展或继承意味着继承是不可能的。

Similarly - A object is final: some time we does not modified the internal state of object so in such case we can specify the object is final object.object final means not variable also final. 类似地 - 一个对象是最终的:有时我们没有修改对象的内部状态,所以在这种情况下我们可以指定对象是最终对象。对象最终意味着不是变量也是最终的。

Once reference variable is made final, it cannot be reassigned to other object. 一旦引用变量为final,就不能将其重新赋值给其他对象。 But can change the contents of the object as long as its fields are not final 但只要字段不是最终字段,就可以更改对象的内容


#3楼

YES it can. 是的,它可以。 Here is an instance where final can boost performance: 这是final可以提升性能的实例:

Conditional compilation is a technique in which lines of code are not compiled into the class file based on a particular condition. 条件编译是一种技术,其中代码行不会根据特定条件编译到类文件中。 This can be used to remove tons of debugging code in a production build. 这可用于删除生产版本中的大量调试代码。

consider the following: 考虑以下:

public class ConditionalCompile {private final static boolean doSomething= false;if (doSomething) {// do first part. }if (doSomething) {// do second part. }if (doSomething) {     // do third part. }if (doSomething) {// do finalization part. }
}

By converting the doSomething attribute into a final attribute, you have told the compiler that whenever it sees doSomething, it should replace it with false as per the compile-time substitution rules. 通过将doSomething属性转换为final属性,您告诉编译器每当它看到doSomething时,它应该根据编译时替换规则将其替换为false。 The first pass of the compiler changes the code to something like this: 编译器的第一遍改变的代码这样

public class ConditionalCompile {private final static boolean doSomething= false;if (false){// do first part. }if (false){// do second part. }if (false){// do third part. }if (false){// do finalization part. }
}

Once this is done, the compiler takes another look at it and sees that there are unreachable statements in the code. 完成此操作后,编译器将再次查看它,并发现代码中存在无法访问的语句。 Since you are working with a top-quality compiler, it doesn't like all those unreachable byte codes. 由于您使用的是高质量的编译器,因此它不喜欢所有那些无法访问的字节代码。 So it removes them, and you end up with this: 所以它删除它们,你最终得到这个:

public class ConditionalCompile {private final static boolean doSomething= false;public static void someMethodBetter( ) {// do first part. // do second part. // do third part. // do finalization part. }
}

thus reducing any excessive codes, or any unnecessary conditional checking. 从而减少任何过多的代码,或任何不必要的条件检查。

Edit: As an example, let's take the following code: 编辑:举个例子,我们来看下面的代码:

public class Test {public static final void main(String[] args) {boolean x = false;if (x) {System.out.println("x");}final boolean y = false;if (y) {System.out.println("y");}if (false) {System.out.println("z");}}
}

When compiling this code with Java 8 and decompiling with javap -c Test.class we get: 使用Java 8编译此代码并使用javap -c Test.class反编译时,我们得到:

public class Test {public Test();Code:0: aload_01: invokespecial #8                  // Method java/lang/Object."<init>":()V4: returnpublic static final void main(java.lang.String[]);Code:0: iconst_01: istore_12: iload_13: ifeq          146: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;9: ldc           #22                 // String x11: invokevirtual #24                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V14: iconst_015: istore_216: return
}

We can note that compiled code includes only the non-final variable x . 我们可以注意到编译的代码只包含非最终变量x This prooves that final variables have impact on performances, at least for this simple case. 这证明了最终变量对性能的影响,至少对于这个简单的情况。


#4楼

Short answer: don't worry about it! 简答:不要担心!

Long answer: 答案很长:

When talking about final local variables keep in mind that using the keyword final will help the compiler optimize the code statically , which may in the end result in faster code. 在谈论最终局部变量时请记住,使用关键字final将有助于编译器静态优化代码,这最终可能导致更快的代码。 For example, the final Strings a + b in the example below are concatenated statically (at compile time). 例如,下面示例中的最终字符串a + b是静态连接的(在编译时)。

public class FinalTest {public static final int N_ITERATIONS = 1000000;public static String testFinal() {final String a = "a";final String b = "b";return a + b;}public static String testNonFinal() {String a = "a";String b = "b";return a + b;}public static void main(String[] args) {long tStart, tElapsed;tStart = System.currentTimeMillis();for (int i = 0; i < N_ITERATIONS; i++)testFinal();tElapsed = System.currentTimeMillis() - tStart;System.out.println("Method with finals took " + tElapsed + " ms");tStart = System.currentTimeMillis();for (int i = 0; i < N_ITERATIONS; i++)testNonFinal();tElapsed = System.currentTimeMillis() - tStart;System.out.println("Method without finals took " + tElapsed + " ms");}}

The result? 结果?

Method with finals took 5 ms
Method without finals took 273 ms

Tested on Java Hotspot VM 1.7.0_45-b18. 在Java Hotspot VM 1.7.0_45-b18上测试。

So how much is the actual performance improvement? 那么实际的性能提升了多少? I don't dare say. 我不敢说。 In most cases probably marginal (~270 nanoseconds in this synthetic test because the string concatenation is avoided altogether - a rare case), but in highly optimized utility code it might be a factor. 在大多数情况下可能是边缘的(在这个综合测试中大约270纳秒,因为完全避免了字符串连接 - 这是一种罕见的情况),但在高度优化的实用程序代码中,它可能是一个因素。 In any case the answer to the original question is yes, it might improve performance, but marginally at best . 在任何情况下,原始问题的答案都是肯定的,它可能会提高性能,但最多只是略微提高

Compile-time benefits aside, I could not find any evidence that the use of the keyword final has any measurable effect on performance. 除了编译时的好处,我找不到任何证据表明关键字final的使用对性能有任何可衡量的影响。


#5楼

Actually, while testing some OpenGL-related code, I found that using the final modifier on a private field can degrade performance. 实际上,在测试一些与OpenGL相关的代码时,我发现在私有字段上使用final修饰符会降低性能。 Here is the start of the class I tested: 这是我测试的课程的开始:

public class ShaderInput {private /* final */ float[] input;private /* final */ int[] strides;public ShaderInput(){this.input = new float[10];this.strides = new int[] { 0, 4, 8 };}public ShaderInput x(int stride, float val){input[strides[stride] + 0] = val;return this;}// more stuff ...

And this is the method I used to test the performance of various alternatives, amongst which the ShaderInput class: 这是我用来测试各种替代方案的性能的方法,其中ShaderInput类:

public static void test4()
{int arraySize = 10;float[] fb = new float[arraySize];for (int i = 0; i < arraySize; i++) {fb[i] = random.nextFloat();}int times = 1000000000;for (int i = 0; i < 10; ++i) {floatVectorTest(times, fb);arrayCopyTest(times, fb);shaderInputTest(times, fb);directFloatArrayTest(times, fb);System.out.println();System.gc();}
}

After the 3rd iteration, with the VM warmed up, I consistently got these figures without the final key word: 在第3次迭代之后,随着VM的预热,我一直得到这些数字而没有最后的关键词:

Simple array copy took   : 02.64
System.arrayCopy took    : 03.20
ShaderInput took         : 00.77
Unsafe float array took  : 05.47

With the final keyword: 使用 final关键字:

Simple array copy took   : 02.66
System.arrayCopy took    : 03.20
ShaderInput took         : 02.59
Unsafe float array took  : 06.24

Note the figures for the ShaderInput test. 请注意ShaderInput测试的数字。

It didn't matter whether I made the fields public or private. 我是将公共场所还是私人场地都无关紧要。

Incidentally, there are a few more baffling things. 顺便说一句,还有一些令人困惑的事情。 The ShaderInput class outperforms all other variants, even with the final keyword. ShaderInput类优于所有其他变体,即使使用final关键字也是如此。 This is remarkable b/c it basically is a class wrapping a float array, while the other tests directly manipulate the array. 这是非常了不起的b / c它基本上是一个包装浮点数组的类,而其他测试直接操作数组。 Have to figure this one out. 必须弄清楚这个。 May have something to do with ShaderInput's fluent interface. 可能与ShaderInput的流畅界面有关。

Also System.arrayCopy actually apparently is somewhat slower for small arrays than simply copying elements from one array to the other in a for loop. 对于小型数组而言,System.arrayCopy实际上显然比在for循环中将元素从一个数组复制到另一个数组要慢一些。 And using sun.misc.Unsafe (as well as direct java.nio.FloatBuffer, not shown here) performs abysmally. 并使用sun.misc.Unsafe(以及直接java.nio.FloatBuffer,此处未显示)执行得非常糟糕。


#6楼

Usually not. 通常不是。 For virtual methods, HotSpot keeps track of whether the method has actually been overridden, and is able to perform optimizations such as inlining on the assumption that a method hasn't been overridden - until it loads a class which overrides the method, at which point it can undo (or partially undo) those optimizations. 对于虚方法,HotSpot会跟踪方法是否实际被覆盖,并且能够在假设方法尚未被覆盖的情况执行优化,例如内联 - 直到它加载一个覆盖方法的类,此时它可以撤消(或部分撤消)这些优化。

(Of course, this is assuming you're using HotSpot - but it's by far the most common JVM, so...) (当然,这假设您正在使用HotSpot - 但它是迄今为止最常见的JVM,所以...)

To my mind you should use final based on clear design and readability rather than for performance reasons. 在我看来,你应该使用基于清晰设计和可读性的final而不是出于性能原因。 If you want to change anything for performance reasons, you should perform appropriate measurements before bending the clearest code out of shape - that way you can decide whether any extra performance achieved is worth the poorer readability/design. 如果您出于性能原因想要更改任何内容,则应在将最清晰的代码变形之前执行适当的测量 - 这样您就可以决定是否所获得的额外性能值得更差的可读性/设计。 (In my experience it's almost never worth it; YMMV.) (根据我的经验,它几乎不值得; YMMV。)

EDIT: As final fields have been mentioned, it's worth bringing up that they are often a good idea anyway, in terms of clear design. 编辑:由于已经提到了最后的领域,所以值得提出的是,无论如何,在清晰的设计方面,它们通常都是个好主意。 They also change the guaranteed behaviour in terms of cross-thread visibility: after a constructor has completed, any final fields are guaranteed to be visible in other threads immediately. 它们还在跨线程可见性方面改变了保证行为:在构造函数完成之后,任何最终字段都保证在其他线程中立即可见。 This is probably the most common use of final in my experience, although as a supporter of Josh Bloch's "design for inheritance or prohibit it" rule of thumb, I should probably use final more often for classes... 这可能是我经验中最常用的final ,虽然作为Josh Bloch的“继承设计或禁止它的设计”的支持者,我应该更频繁地使用final来进行课程...

在Java中使用final关键字可以提高性能吗?相关推荐

  1. fianl属性 java_在Java中使用Final关键字可以提高性能吗?

    是的可以.下面是一个最终可以提高性能的实例: 条件编译是一种技术,在这种技术中,代码行不会根据特定条件编译到类文件中.这可用于删除生产生成中的大量调试代码. 考虑以下几点:public class C ...

  2. 深入理解Java中的final关键字

    深入理解Java中的final关键字 http://www.importnew.com/7553.html Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什 ...

  3. (转)深入理解Java中的final关键字

    转自:http://www.importnew.com/7553.html Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方 ...

  4. java final 变量 好处_深入理解Java中的final关键字

    Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使 ...

  5. java中final是啥意思_(转)深入理解Java中的final关键字

    Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使 ...

  6. 详解java中的final关键字

    概述 final 简介 final关键字可用于多个场景,且在不同场景具有不同的作用.首先,final是一个非访问修饰符,仅适用于变量,方法或类.下面是使用final的不同场景: 上面这张图可以概括成: ...

  7. 浅谈Java中的final关键字

    浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...

  8. 浅析Java中的final关键字

    浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...

  9. java final 修改_“无法改变的设计”——浅谈Java中的final关键字

    在Java中,final关键字可以用来修饰类.变量(包括成员变量和局部变量).方法,下面从这三个方面分别说明. final方法 当一个方法被final修饰时,表明这个方法不能被子类重写. 下面程序试图 ...

最新文章

  1. SAP MM ME21N 创建PO时报错 - Net price in CNY becomes too large – 之对策
  2. js 复制图片_不会做ppt?Reveal.js让你复制粘贴另类拉风,简洁优雅又低调
  3. 相关系数excel_跟着思想学外汇-如何用Excel计算货币相关性
  4. 1349. 修理牛棚【难度: 中 / 思维 贪心】
  5. mysql数据库使用命令导入sql文件
  6. 法流程图_【对反应过程的笔记整理方法——时间轴法】
  7. spring3 常见异常解决
  8. 我就拜你为师的飞秋爱好者
  9. Beta函数与Gamma函数及其与Beta分布的关系
  10. Dropbox安装包官网下载失败的解决方法
  11. Linux文件I/O实验报告
  12. 4个女人要过一座桥的问题
  13. 原码、反码、补码和真值
  14. python--data.dropna
  15. fake news:使用区块链技术来保证新闻中数字媒体的真实性。
  16. GitHub 上 1400星的 Git 魔法书火了
  17. Java中增强for循环 for(int x:number) continue中的label: 标签 continue标签
  18. 北京计算机科学技术研究所,北京大学计算机科学技术研究所
  19. [Objective-C]第二天
  20. 控制微信小程序web view的返回按钮

热门文章

  1. oracle 创建数据库 表空间 用户 授权和toad导入导出数据库
  2. Android中的定时器AlarmManager
  3. 专业程序员成长之路之基础基础!
  4. Windows usb设备正在使用中
  5. 自适应col自动换行显示_10kV配网自适应综合型馈线自动化技术的测试问题及解决措施...
  6. C#从零单排上王者系列---元组
  7. 第一阶段团队成员贡献打分
  8. JAVA常用知识总结(七)——Spring
  9. Cortex-A9 UART
  10. LeetCode-1.Two Sum