Bytecodes are not significantly more or less efficient if you use final, because Java bytecode compilers usually have little to do with optimization. The performance bonus (if any) will be in the native code generated by the JIT compiler.
Theoretically, using final gives a hint to the JIT compiler, which should help it optimize. In practice, the latest HotSpot JIT compilers can do a better job ignoring your hints. For example, a modern JIT compiler typically does a global analysis to find out if a given method call is a leaf method in the context of the classes currently loading. This analysis is more accurate than your final hints can be, and the runtime may even detect when a new class is loading, which invalidates the analysis ... and repeats the analysis and generation of native code for the affected code.
Therefore, it is best practice to use the final (in the broad sense) expression of your design intentions and achieve other necessary semantic effects. (For example, using the final modifier can play an important role in implementing thread-safe types of immutable types.) If you use final as an optimization hint, you will not achieve significant results, and you will make your code more difficult to modify and extend.
font: link
source share