在Java中使用Final关键字可以提高性能吗?

在Java中使用Final关键字可以提高性能吗?

在Java中,我们看到很多地方final关键字可以使用,但它的使用并不常见。

例如:

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

在上述情况下,str可以final但这通常都会被搁置。

当一个方法永远不会被覆盖时,我们可以使用Final关键字。类似地,在不被继承的类的情况下。

在任何或所有这些情况下使用Final关键字真的可以提高性能吗?如果是,那怎么做?请解释一下。如果正确使用final对于性能来说,真正重要的是,Java程序员应该养成什么样的习惯才能更好地使用关键字呢?


慕工程0101907
浏览 1589回答 3
3回答

翻过高山走不出你

是的可以。下面是一个最终可以提高性能的实例:条件编译是一种技术,在这种技术中,代码行不会根据特定条件编译到类文件中。这可用于删除生产生成中的大量调试代码。考虑以下几点:public&nbsp;class&nbsp;ConditionalCompile&nbsp;{ &nbsp;&nbsp;private&nbsp;final&nbsp;static&nbsp;boolean&nbsp;doSomething=&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(doSomething)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;do&nbsp;first&nbsp;part.&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(doSomething)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;do&nbsp;second&nbsp;part.&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(doSomething)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;do&nbsp;third&nbsp;part.&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(doSomething)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;do&nbsp;finalization&nbsp;part.&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;}}通过将DoSomething属性转换为最终属性,您已经告诉编译器,每当它看到DoSomething时,它应该按照编译时替换规则用false替换它。编译器的第一次传递将代码更改为某物就像这样:public&nbsp;class&nbsp;ConditionalCompile&nbsp;{ &nbsp;&nbsp;private&nbsp;final&nbsp;static&nbsp;boolean&nbsp;doSomething=&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(false){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;do&nbsp;first&nbsp;part.&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(false){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;do&nbsp;second&nbsp;part.&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(false){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;do&nbsp;third&nbsp;part.&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(false){ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;do&nbsp;finalization&nbsp;part.&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;}}一旦完成,编译器将再次查看它,并看到代码中有一些不可访问的语句。由于您使用的是高质量的编译器,所以它不喜欢所有那些无法访问的字节码。所以它移除了它们,你就得到了这样的结果:public&nbsp;class&nbsp;ConditionalCompile&nbsp;{ &nbsp;&nbsp;private&nbsp;final&nbsp;static&nbsp;boolean&nbsp;doSomething=&nbsp;false; &nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;someMethodBetter(&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;do&nbsp;first&nbsp;part.&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;do&nbsp;second&nbsp;part.&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;do&nbsp;third&nbsp;part.&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;do&nbsp;finalization&nbsp;part.&nbsp; &nbsp;&nbsp;}}从而减少了任何过多的代码,或任何不必要的有条件检查。编辑:作为一个示例,让我们使用以下代码:public&nbsp;class&nbsp;Test&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;final&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boolean&nbsp;x&nbsp;=&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(x)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("x"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;boolean&nbsp;y&nbsp;=&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(y)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("y"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(false)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("z"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}}在用Java 8编译此代码和用javap -c Test.class我们得到:public&nbsp;class&nbsp;Test&nbsp;{ &nbsp;&nbsp;public&nbsp;Test(); &nbsp;&nbsp;&nbsp;&nbsp;Code: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0:&nbsp;aload_0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1:&nbsp;invokespecial&nbsp;#8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Method&nbsp;java/lang/Object."<init>":()V &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4:&nbsp;return &nbsp;&nbsp;public&nbsp;static&nbsp;final&nbsp;void&nbsp;main(java.lang.String[]); &nbsp;&nbsp;&nbsp;&nbsp;Code: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0:&nbsp;iconst_0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1:&nbsp;istore_1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2:&nbsp;iload_1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3:&nbsp;ifeq&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6:&nbsp;getstatic&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Field&nbsp;java/lang/System.out:Ljava/io/PrintStream; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9:&nbsp;ldc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#22&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;String&nbsp;x &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;11:&nbsp;invokevirtual&nbsp;#24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Method&nbsp;java/io/PrintStream.println:(Ljava/lang/String;)V &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14:&nbsp;iconst_0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;15:&nbsp;istore_2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;16:&nbsp;return}我们可以注意到,编译后的代码只包含非最终变量。x..这表明最终变量对性能有影响,至少在这个简单的情况下是这样的。

慕神8447489

通常不会。对于虚拟方法,HotSpot会跟踪该方法是否具有其实被重写,并且能够执行优化,例如在假设方法没有被重写-直到它加载一个重写方法的类,此时它可以撤消(或部分撤消)这些优化。(当然,这是假设您在使用HotSpot-但它是目前为止最常见的JVM,所以.)在我看来你应该用final基于清晰的设计和可读性,而不是出于性能原因。如果您出于性能原因想要更改任何内容,那么在将最清晰的代码变形之前,您应该执行适当的度量-这样您就可以决定是否有任何额外的性能值得进行较差的可读性/设计。(以我的经验,这几乎是不值得的;YMMV。)编辑:由于最后的领域已经提到,值得提出的是,他们往往是一个好主意,无论如何,就明确的设计。它们还改变了跨线程可见性方面的保证行为:在构造函数完成后,所有最终字段都保证在其他线程中立即可见。这可能是最常用的final根据我的经验,虽然我支持乔希·布洛赫的“要么继承要么禁止”的经验法则,但我可能应该使用final更多的是为了上课.。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java