2

My teacher says that we can use final to improve efficiency. I tried to do the test, but I find that adding a final method modifier can actually reduce the efficiency.

My test is like this:

ClassTest1:

public class ClassTest1 {
  public final String getName() {
    return name;
  } 
  public final void setName(String name) {
    this.name = name;
  } 
  private   String  name;
}

ClassTest2:

public class ClassTest2 {
  public   String getName() {
    return name;
  } 
  public   void setName(String name) {
    this.name = name;
  } 
  private String  name;
}

Main Test Method:

public static void main(String[] args) {
    ClassTest1 ct1=new ClassTest1();
    ClassTest2 ct2=new ClassTest2();
    Long t1=System.currentTimeMillis();
    for (int i = 0; i <1000000 ; i++) {
        ct1.getName();
    }
    Long t2=System.currentTimeMillis();
    for (int i = 0; i <1000000 ; i++) {
        ct2.getName();
    }
    Long t3=System.currentTimeMillis();
    System.out.println("add final decorate cost time:"+(t2-t1));
    System.out.println("not add final decorate cost time:"+(t3-t2));
}

Why does adding final cost more time than not adding the final method?

Arnold Schrijver
  • 3,588
  • 3
  • 36
  • 65
flower
  • 2,212
  • 3
  • 29
  • 44
  • 1
    Adding the final keyword to a method's signature prevents it from being overridden in any child class, efficiency has absolutely nothing to do with this. – Jacob G. Jan 28 '17 at 17:12
  • 1
    `final` cannot make things slower. It will usually not make things faster either - in most cases the compiler can work out when something is _effectively `final`_. `final` is used to make code more **readable**. – Boris the Spider Jan 28 '17 at 17:12
  • 2
    You didnt add a jvm warmup, so changing the test to execute the version with final as second should change the result – k5_ Jan 28 '17 at 17:13
  • @BoristheSpider,in fact,when I add the final keyword,it is more slow from the test result. – flower Jan 28 '17 at 17:15
  • @JacobG. in theory you can avoid the overhead of virtual dispatch on final methods. But the jvm is quite good at removing unnecessary virtual dispatches. – k5_ Jan 28 '17 at 17:15
  • 3
    @Sarly see other comments; your benchmarks are fundamentally flawed. – Boris the Spider Jan 28 '17 at 17:15
  • 1
    @k5_,can you tell me how to add a jvm warmup?I can not understand what you say. – flower Jan 28 '17 at 17:59
  • 1
    @Sarly A good explanation is there: – Misi May 18 '18 at 09:55
  • Please look into using `jmh` for writing benchmarks. For explanation of "warmup", look at some description of JIT in Java (Wikipedia could be a good starting point). –  Jul 19 '18 at 13:51
  • Now that's cool. Answering a 16+ months old question and getting accepted within an hour. Thanks for the quick comeback. Not many "Revival" badges I have, one more thanks to your question! – GhostCat Jul 19 '18 at 14:24

1 Answers1

2

There are two aspects here:

  • Measuring Java performance is hard, see here. Most likely, your numbers are simply not sound
  • As the comments say: final on methods only affects whether they can be overridden. Theoretically, that can affect runtime performance. When the JIT compiler knows that a method can't be overridden, it can decide to directly inline the method body, without any kind of additional checking. When the method isn't final, it could be wrong to execute the inlined body of the base method, therefore some sort of check is necessary before said execution.

Boiling down to: if at all, using that keyword helps avoiding a single check at runtime when the method is invoked. In that sense, we are probably talking nanoseconds of gains.

So, yes, there is a theoretical aspect of runtime performance, but the real usage of final is to communicate intent to human readers.

GhostCat
  • 137,827
  • 25
  • 176
  • 248