-1

Marking a method parameter as final is needed to allow for variable access by inner anonymous classes and is a useful coding-tool for enforcing certain variable use conventions within the method.

Apart from that, is there some other compilation-related motivation to use the final-keyword? Specifically, does it give the compiler any hints which facilitate some specific optimization that would otherwise not be performed? Or is the compiler smart enough to always recognize if a variable is never modified anyways?

For example, I'm thinking whether there is any difference how the variables are passed into the method. E.g. a variable of primitive type (int, byte, etc.) needs to be copied when passed into the method to prevent any modifications to trickle out into the calling code, whereas if the parameter is marked final, it could be "passed by reference" without such concerns, i.e. no copy-operation would be needed.

But let's keep the question more general than this example:

Are there scenarios where adding final to a method parameter will change the generated byte-code?

Markus A.
  • 12,349
  • 8
  • 52
  • 116
  • It's good practice to use `final` method parameter specially for `public` methods to avoid any modification in the passed object. – Braj May 30 '14 at 20:02
  • It could also be used in [constant folding](http://en.wikipedia.org/wiki/Constant_folding). No references are involved with primitives, so the value passed is always a "copy". – Elliott Frisch May 30 '14 at 20:03
  • Related: [Why should I use the keyword “final” on a method parameter in Java?](http://stackoverflow.com/q/500508/1065197) – Luiggi Mendoza May 30 '14 at 20:09
  • 1
    @Braj `final` applies to the reference, not the object it refers to. `final` on a parameter just prevents you from changing what the parameter points to. It does not protect the referenced object. – Jim Garrison May 30 '14 at 20:11
  • @JimGarrison yes you are absolutely 100% right. – Braj May 30 '14 at 20:14
  • @ElliottFrisch Not sure I follow your second sentence. If I have an `int`, it's stored somewhere in memory. So, if I want to access it, the compiler will generate some sort of "load/store memory address XYZ" statement. Now, if I have a non-final parameter, it needs to make a copy and generate "load/store address ABC" inside the method instead so that I don't overwrite the other value. But if it's final, "load XYZ" would be fine inside the method as "store XYZ" is forbidden, so the compiler can simply re-use the same memory location rather than having to copy the value, no? – Markus A. May 30 '14 at 20:15
  • 1
    Hint: since Java 8, final is not needed anymore if the variable is used inside an inner class. The compiler is able to know that the parameter is effectively final. And the JIT is smarter than the compiler. I'd be very surprised if adding final to parameters had any affect on performance. – JB Nizet May 30 '14 at 20:15
  • @ElliottFrisch, As for constant folding, like Markus A pointed out, if it's a local var or a function arg, then the compiler should be smart enough to know whether the code changes it or not. So the question is, why mark a _local_ variable `final` other than for documentation purposes or to make it visible to an anonymous inner class? – Solomon Slow May 30 '14 at 20:17
  • @jameslarge To protect yourself from modifying a constant? – Elliott Frisch May 30 '14 at 20:22
  • @ElliottFrisch, I don't need to protect myself. If I mark a _private_ variable `final` it is only for the benefit of some programmer (maybe myself) who wants to re-use my code for some new purpose in the future. I want to help that programmer understand my original intent. Of course he/she could figure out that the variable does not change, but if I write `final`, then the programmer doesn't _have_ to figure it out: `final` is proof that the 'variable' actually is constant. In that sense, `final`, like `assert`, like well-chosen variable and method names, is a form of documentation. – Solomon Slow Jun 02 '14 at 13:36

1 Answers1

1

No there is not. This is purely a compile time check.

Note that bytecode is higher level then you seem to think - in particular there's no raw memory addresses. All parameter passing is abstracted away. Also, the Java compiler does very little optimization. The JIT is responsible for doing all the optimization at runtime.

Furthermore at the actual machine code level, passing a single word parameter by reference likely isn't going to optimize anything. Under normal circumstances, copying it will be faster (since it's in a register anyway). But again, this is all low level implementation details that the JIT worries about, not the purview of bytecode.

Antimony
  • 37,781
  • 10
  • 100
  • 107
  • Makes sense. Do you know if there is a reference for this in the JLS somewhere? – Markus A. May 31 '14 at 04:34
  • @Markus The JLS rarely talks about bytecode. Perhaps you're thinking of the JVMS. Anyway, the question isn't addressed specifically, but seeing as there's no such thing as a final local variable or parameter at the bytecode level (and barely any concept of a local variable at all), it's difficult to believe that it would make a difference. If you wanted to be 100% sure, you'd have to read the compiler source. – Antimony May 31 '14 at 10:36
  • As of Java 8, final modifiers on method parameters are preserved in the [MethodParameters attribute](http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.24), available at runtime through [Parameter.getModifiers()](http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Parameter.html#getModifiers--). final parameters still don't change the method bytecode, of course. – Jeffrey Bosboom Jun 03 '14 at 16:13
  • @Jeffrey Thanks for the info. I haven't had time to go over the Java 8 specs in detail yet. – Antimony Jun 04 '14 at 05:28