The bytecodes are not significantly more or less efficient if you use final because Java bytecode compilers typically do little in the way optimization. The efficiency bonus (if any) will be in the native code produced by the JIT compiler.
In theory, using the final provides a hint to the JIT compiler that should help it optimize. In practice, recent HotSpot JIT compilers can do a better job by ignoring your hints. For instance, a modern JIT compiler typically performs a global analysis to find out if a given method call is a call to a leaf method in the context of the application's currently loaded classes. This analysis is more accurate than your final hints can be, and the runtime can even detect when a new class is loaded that invalidates the analysis ... and redo the analysis and native code generation for the affected code.
So best practice is to use final to (broadly speaking) express your design intentions, and to achieve other semantic effects that you require. (For instance using the final modifier can play an important role in implementing thread-safe immutable types.) If you use final as an optimization hint, you won't achieve much, and you will make your code harder to modify and extend.
font: link