36

My question is pretty simple:
Does the compiler treat all the methods in a final class as being final themselves? Does adding the final keyword to methods in a final class has any effect?

I understood that final methods have a better chance of getting inlined and this is why I am asking.

Thanks in advance.

Acidic
  • 6,154
  • 12
  • 46
  • 80

3 Answers3

40

You're correct, all methods in a final class are implicitly final.

See here:

"Note that you can also declare an entire class final. A class that is declared final cannot be subclassed. This is particularly useful, for example, when creating an immutable class like the String class."

And here:

All methods in a final class are implicitly final.

This may also be of interest for you: Performance tips for the Java final keyword

EboMike
  • 76,846
  • 14
  • 164
  • 167
  • 3
    To be pedantic, whether or not the methods are implicitly final is moot; there is no opportunity to attempt to override them! – Oliver Charlesworth Jan 07 '12 at 01:12
  • 1
    Does this mean that the compiler will treat those methods as final? (inlining) @OliCharlesworth True, but there is a difference in how the compiler treats virtual and final methods. – Acidic Jan 07 '12 at 01:14
  • 1
    @Acidic: See the third link I just added. You probably don't need to go out of your way to declare things as final. But yes, to the compiler, those methods are considered "final". – EboMike Jan 07 '12 at 01:16
  • 3
    Note that in any modern JVM, the only place final gains you any efficiency is for fields. The JVM performs its own analysis to decide what methods can be inlined, what local variables are written only once, and so forth. – Russell Zahniser Jan 07 '12 at 01:19
  • I think it's safe to say that most Java environments (even Android's Dalvik at 2.2 and later) have a JIT compiler, which can make much more informed decisions on what to inline and when, as well as other optimizations. Trying to guide it with the final keyword is a noble gesture, but most likely not necessary. – EboMike Jan 07 '12 at 01:26
  • Yes ... there are lots of sources that say that marking a method as `final` helps performance. They all date from 15+ years ago. It *no longer* helps. – Stephen C Oct 30 '18 at 07:34
9

Does the compiler treat all the methods in a final class as being final themselves?

In effect, yes it does. A method in a final class cannot be overridden. Adding (or removing) a final keyword to a method makes no difference to this rule.

Does adding the final keyword to methods in a final class has any effect?

In practice, it has minimal effect. It has no effect on the rules on overriding (see above), and no effect on inlining (see below).

It is possible to tell at runtime if a method was declared with a final keyword ... using reflection to look at the method's flags. So it does have some effect, albeit an effect that it irrelevant to 99.99% of programs.

I understood that final methods have a better chance of getting inlined and this is why I am asking.

This understanding is incorrect. The JIT compiler in a modern JVMs keeps track of which methods are not overridden in the classes loaded by an application. It uses this information, and the static types to determine whether a particular call requires virtual class dispatching or not. If not, then inlining is possible, and will be used depending on how large the method body is. In effect, the JIT compiler ignores the presence / absence of final, and uses a more accurate method to detect method calls where inlining of the method is allowable.

(In fact it is more complex than this. An application can dynamically load subclasses that cause the JIT compiler's method override analysis to become incorrect. If this happens, the JVM needs to invalidate any effected compiled methods and cause them to be recompiled.)


The bottom line is:

  • There is NO performance advantage in adding final to methods in final classes.

  • There might be a performance advantage in final to methods in non-final classes, but only if you are using an old Sun JVM, or some other Java / Java-like platform with a poor quality JIT compiler.

If you care about performance, it is better to use an up-to-date / high performance Java platform with a decent JIT compiler than to pollute your code-base with final keywords that are liable to cause you problems in the future.


You wrote in a comment:

@RussellZahniser I have read differently in many places.

The internet is full of old information, much of which is out of date ... or was never correct in the first place.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Thank you, that is a very interesting read. Is there any official information or some sort of definitive tests & results on the matter? – Acidic Jan 07 '12 at 02:14
  • Also, in a relevant question I've asked before, I have been led to understand that `final` methods do in fact have a higher chance of being inlined: http://stackoverflow.com/questions/8639704/probability-of-getters-and-setters-getting-inlined-by-the-compiler – Acidic Jan 07 '12 at 02:16
  • 1
    @Acidic - my understanding is that `final` makes no difference, and I know of no real evidence that contradicts this. If you really want a definitive answer, look at the OpenJDK sourcecode and see what the JIT compiler(s) actually do. – Stephen C Jan 07 '12 at 02:29
  • I think that is a bit too time consuming for me. – Acidic Jan 07 '12 at 04:03
  • 1
    @Acidic - your choice. It will save you time if you trust everything I say. (And if you lend be 20 dollars, I'll pay you back next week.) – Stephen C Sep 18 '12 at 07:36
  • 2
    Illuminating answer - finally we don't need final. In the end, we won't even need to type anything because the compiler will figure out everything. – bugfoot Mar 19 '17 at 13:05
5

May be the compiler treats them as final.

The following prints "false":

final class FinalClass {
    public void testMethod() {}
}

Method method = FinalClass.class.getDeclaredMethod("testMethod");
int m = method.getModifiers();
System.out.println(Modifier.isFinal(m));
Bhesh Gurung
  • 50,430
  • 22
  • 93
  • 142