为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕工程0101907 2019-07-05 12:30:09
在Java中使用Final关键字可以提高性能吗?在Java中,我们看到很多地方final关键字可以使用,但它的使用并不常见。例如:String str = "abc";System.out.println(str);在上述情况下,str可以final但这通常都会被搁置。当一个方法永远不会被覆盖时,我们可以使用Final关键字。类似地,在不被继承的类的情况下。在任何或所有这些情况下使用Final关键字真的可以提高性能吗?如果是,那怎么做?请解释一下。如果正确使用final对于性能来说,真正重要的是,Java程序员应该养成什么样的习惯才能更好地使用关键字呢?
查看完整描述

3 回答

?
翻过高山走不出你

TA贡献1875条经验 获得超3个赞

是的可以。下面是一个最终可以提高性能的实例:

条件编译是一种技术,在这种技术中,代码行不会根据特定条件编译到类文件中。这可用于删除生产生成中的大量调试代码。

考虑以下几点:

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. 
    }}

通过将DoSomething属性转换为最终属性,您已经告诉编译器,每当它看到DoSomething时,它应该按照编译时替换规则用false替换它。编译器的第一次传递将代码更改为某物就像这样:

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. 

    }}

一旦完成,编译器将再次查看它,并看到代码中有一些不可访问的语句。由于您使用的是高质量的编译器,所以它不喜欢所有那些无法访问的字节码。所以它移除了它们,你就得到了这样的结果:

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. 

  }}

从而减少了任何过多的代码,或任何不必要的有条件检查。

编辑:作为一个示例,让我们使用以下代码:

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");
        }
    }}

在用Java 8编译此代码和用javap -c Test.class我们得到:

public class Test {
  public Test();
    Code:
       0: aload_0       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static final void main(java.lang.String[]);
    Code:
       0: iconst_0       1: istore_1       2: iload_1       3: ifeq          14
       6: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
       9: ldc           #22                 // String x
      11: invokevirtual #24                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      14: iconst_0      15: istore_2      16: return}

我们可以注意到,编译后的代码只包含非最终变量。x..这表明最终变量对性能有影响,至少在这个简单的情况下是这样的。


查看完整回答
反对 回复 2019-07-05
?
慕神8447489

TA贡献1780条经验 获得超1个赞

通常不会。对于虚拟方法,HotSpot会跟踪该方法是否具有其实被重写,并且能够执行优化,例如在假设方法没有被重写-直到它加载一个重写方法的类,此时它可以撤消(或部分撤消)这些优化。

(当然,这是假设您在使用HotSpot-但它是目前为止最常见的JVM,所以.)

在我看来你应该用final基于清晰的设计和可读性,而不是出于性能原因。如果您出于性能原因想要更改任何内容,那么在将最清晰的代码变形之前,您应该执行适当的度量-这样您就可以决定是否有任何额外的性能值得进行较差的可读性/设计。(以我的经验,这几乎是不值得的;YMMV。)

编辑:由于最后的领域已经提到,值得提出的是,他们往往是一个好主意,无论如何,就明确的设计。它们还改变了跨线程可见性方面的保证行为:在构造函数完成后,所有最终字段都保证在其他线程中立即可见。这可能是最常用的final根据我的经验,虽然我支持乔希·布洛赫的“要么继承要么禁止”的经验法则,但我可能应该使用final更多的是为了上课.。


查看完整回答
反对 回复 2019-07-05
  • 3 回答
  • 0 关注
  • 1587 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号