Christopher Meyer

About Christopher Meyer

Chris works as a researcher and is eagerly looking for bugs in SSL/TLS, the Java platform and various applications. In addition, he is primarily interested in secure coding and exploiting coding mistakes.

Using the final keyword on method parameters

After some own confusion which specific meaning final declared method parameters have this blog entry will try to clarify this.

At least the final keyword on method parameters can be seen as an indicator for the Java compiler that this parameter can not be reassigned to another reference. Java parameter handling is always Call by Value (yes, even when dealing with Objects) and here comes why.: It is true, that Java handles a reference to the Object when dealing with non-primitive data types. The Object itself is not passed from the callee to the target function! Instead a reference is passed that points to the desired Object. But this reference is not equal to the one on callee side since it is just a copy. What is passed to a function is a copied reference as value – ok, everyone’s still on board? :-) Maybe Java should use the more matching explanation Call by Copied Reference as Value.

To sum up:

Java exclusively passes ALL method parameters (primitive data types or references to objects) in Call by Value style!

As a proof for this let’s have a look at the following demo code and its output.

 
/**
 * Call by Value Test Application.
 *
 * @author Christopher Meyer
 * @version 0.1 
 * Apr 21, 2012
 */
public class CBVTest {

    public static void main(String[] args) {
        Integer mainInternInteger = new Integer(1);

        /*
         * Even references are copied during calls!
         *
         * Explanation Objects are never passed, only references to them, BUT
         * references are copied! So only reference COPIES reach the method.
         * Neither changes to the reference inside/outside the method will
         * influence the counterpart.
         *
         * Maybe it should be called "Call by Copied Reference as Value".
         */

        class RunMe implements Runnable {

            Integer runnerInternInteger;

            public RunMe(Integer i) {
                runnerInternInteger = i;

                /*
                 * The following operation will have no effect on the main
                 * thread, since the reference to "i" is a copied one.
                 * Interfacing the "caller" reference is prevented.
                 */
                i = new Integer(3);
            }

            @Override
            public void run() {
                while (true) {
                    System.out.println(runnerInternInteger.intValue() 
                            + "\t (runner intern value)");
                }
            }
        }

        Thread runner = new Thread(new RunMe(mainInternInteger));
        runner.start();

        // Create a new object and assign it to "mainInternInteger".
        mainInternInteger = new Integer(2);
        while (true) {
            System.out.println(
                    mainInternInteger.intValue() + "\t (main intern value)");
        }
    }
}

The output of the code looks like this:

...
2     (main intern value)
2     (main intern value)
2     (main intern value)
2     (main intern value)
1     (runner intern value)
2     (main intern value)
1     (runner intern value)
2     (main intern value)
1     (runner intern value)
2     (main intern value)
1     (runner intern value)
1     (runner intern value)
1     (runner intern value)
1     (runner intern value)
1     (runner intern value)
 ...

So neither the assignment to the handled parameter (i = new Integer(3)), nor the reassignment from the calling class (mainInternInteger = new Integer(2)) have any influence on each other.

So what is it worth if it isn’t really necessary?

If added to the Constructor of RunMe (public RunMe(final Integer i)) the reassignment i = new Integer(3) throws an exception: Exception in thread “main” java.lang.RuntimeException: Uncompilable source code – final parameter i may not be assigned. It prevents failures related to unintentional reassignment. Accidental assignments to the handled parameter will always fail! final forces a developer to produce accurate code.

The final keyword is not part of the method signature. So if declared final or not, the compiled code will be identical (everyone can easily check this by using diff). This means that a method can’t be overloaded by declaring the method parameters once final and once not. Since the byte code remains identical it also has absolutely no influence on performance.

To confuse even more keep in mind that inner classes require to define a variable final when the variable can be modified (for example when dealing with anonymous inner classes for Threads – if this isn’t clear to you consider multiple variables in the same context with identical names that can be altered).

Reference: Using the final keyword on method parameters from our JCG partner Christopher Meyer at the Java security and related topics blog.

Related Whitepaper:

Bulletproof Java Code: A Practical Strategy for Developing Functional, Reliable, and Secure Java Code

Use Java? If you do, you know that Java software can be used to drive application logic of Web services or Web applications. Perhaps you use it for desktop applications? Or, embedded devices? Whatever your use of Java code, functional errors are the enemy!

To combat this enemy, your team might already perform functional testing. Even so, you're taking significant risks if you have not yet implemented a comprehensive team-wide quality management strategy. Such a strategy alleviates reliability, security, and performance problems to ensure that your code is free of functionality errors.Read this article to learn about this simple four-step strategy that is proven to make Java code more reliable, more secure, and easier to maintain.

Get it Now!  

Leave a Reply


× three = 6



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books