Method arguments

With an understanding of the difference between references and objects it is possible to understand how arguments are passed to methods, and more importantly, what happens when a method modifies one of these arguments. For instance, if a StringBuffer is passed to a method, and that method modifies it, does the caller of the method see the change to that StringBuffer, or does it retain a view to the StringBuffer’s original value?

Programming languages handle this possibility in two different ways, neither of which is inherently right or wrong:

  • Pass by value: with this approach any changes made to an argument will not be seen by the caller. In the example mentioned, the caller would retain a view to the original StringBuffer, and the method would work with a copy of that object.

  • Pass by reference: with this approach the caller will see any changes made to an argument inside a method when the method completes. With pass by reference, a reference to the object is passed, and therefore both parties are modifying the same underlying object when they use that reference.

Java does not easily fit into either of these categories.

When primitives are passed as arguments to a method, Java uses a pass by value approach. This means that the caller does not see any changes the method makes. This can be seen in the following example:

package parameters;

public class Primatives {

    public static void main(String[] args) {

        int num1 = 5;

        System.out.println("Value at point 1 is "+num1);

        changeMe(num1);

        System.out.println("Value at point 3 is "+num1);         

    }

     

    private static void changeMe(int num) {

        num += 5;

        System.out.println("Value at point 2 is "+num);

    }

}

In this case, the method changeMe receives the value held by num1 (5). This is actually a copy of the value held by of num1, however, therefore any modification to this value inside changeMe will not be seen by the main method. This program therefore produces the following output:

Value at point 1 is 5

Value at point 2 is 10

Value at point 3 is 5

When a program passes an object reference to a method, however, things become more complex. Arguments are still passed by value, but to complicate matters, it is the reference to the object that is passed by value. This is an important distinction that even many experienced Java programmers do not fully understand. In order to understand the implications, consider the following example:

package parameters;

public class PassObject1 {

    public static void main(String[] args) {

        StringBuffer sb = new StringBuffer("Hello");

        System.out.println("Value at point 1 is "+sb);

        changeMe(sb);

        System.out.println("Value at point 3 is "+sb);     

    }

 

    private static void changeMe(StringBuffer sb1) {

        sb1 = new StringBuffer("Hello World");

        System.out.println("Value at point 2 is "+sb1);

    }

}

This example behaves the same as the primitive-based example. A copy of the sb reference is passed to the changeMe method: the changeMe method then modifies which object on the heap this reference is referring to. Naturally, changing the value of this new object does not impact the original object. This can be seen in figure 11-3:

Figure 11-3

This program therefore prints:

Value at point 1 is Hello

Value at point 2 is Hello World

Value at point 3 is Hello

Make sure you fully understand this distinction. When the method is invoked, a copy of the original reference is created, and this copy refers to the same underlying object. Therefore, the memory addresses held by the two references are the same when changeMe is invoked.

Inside changeMe, the memory address of the copied references is changed so that it points to another object. This has absolutely no impact on the original reference held by the main method.

Compare this with the following program:

package parameters;

 

public class PassObject2 {

 

    public static void main(String[] args) {

        StringBuffer sb = new StringBuffer("Hello");

        System.out.println("Value at point 1 is "+sb);

        changeMe(sb);

        System.out.println("Value at point 3 is "+sb);     

    }

 

    private static void changeMe(StringBuffer sb1) {

        sb1.append(" World");

        System.out.println("Value at point 2 is "+sb1);

     }

}

Rather than modifying the reference, the changeMe method is modifying the object that the sb1 parameter refers to, and this makes a big difference to the behavior of the program.

Remember, a copy of the sb reference from the main method has been passed to the changeMe method, but both the original and the copy are referring to the same object on the heap. As a result, the changeMe method now directly affects the value of the object created by the main method. As a result, the program prints the following:

Value at point 1 is Hello

Value at point 2 is Hello World

Value at point 3 is Hello World

This can be visualized as seen in figure 11-4:

Figure 11-4

I cannot stress enough how important it is that you understand these distinctions if you want to work effectively with Java. Take these examples and play around with them in Eclipse so you can assure yourself you understand what is happening in each case.

One final point worth emphasizing is the behavior of immutable objects such as Strings. Because there is no way that a method can modify the underlying value of an immutable object, this has an impact on the way argument passing works: specifically, it is not possible for the called method to alter the value of the object in a manner that will be reflected to the calling method:

package parameters;

public class PassObject3 {

    public static void main(String[] args) {

        String s = "Hello";

        System.out.println("Value at point 1 is "+s);

        changeMe(s);

        System.out.println("Value at point 3 is "+s);

    }

 

    private static void changeMe(String s) {

        s += " World";

        System.out.println("Value at point 2 is "+s);

    }

}

This produces the following result:

Value at point 1 is Hello

Value at point 2 is Hello World

Value at point 3 is Hello

The key to understanding this program is the following line:

s += " World";

Due to the fact that Strings are immutable, this line causes a new String object to be created: it does not change the value of the String originally created in the main method.

A Software Engineer Learns Java and Object Orientated Programming
titlepage.xhtml
part0000_split_000.html
part0000_split_001.html
part0000_split_002.html
part0000_split_003.html
part0000_split_004.html
part0000_split_005.html
part0000_split_006.html
part0000_split_007.html
part0000_split_008.html
part0000_split_009.html
part0000_split_010.html
part0000_split_011.html
part0000_split_012.html
part0000_split_013.html
part0000_split_014.html
part0000_split_015.html
part0000_split_016.html
part0000_split_017.html
part0000_split_018.html
part0000_split_019.html
part0000_split_020.html
part0000_split_021.html
part0000_split_022.html
part0000_split_023.html
part0000_split_024.html
part0000_split_025.html
part0000_split_026.html
part0000_split_027.html
part0000_split_028.html
part0000_split_029.html
part0000_split_030.html
part0000_split_031.html
part0000_split_032.html
part0000_split_033.html
part0000_split_034.html
part0000_split_035.html
part0000_split_036.html
part0000_split_037.html
part0000_split_038.html
part0000_split_039.html
part0000_split_040.html
part0000_split_041.html
part0000_split_042.html
part0000_split_043.html
part0000_split_044.html
part0000_split_045.html
part0000_split_046.html
part0000_split_047.html
part0000_split_048.html
part0000_split_049.html
part0000_split_050.html
part0000_split_051.html
part0000_split_052.html
part0000_split_053.html
part0000_split_054.html
part0000_split_055.html
part0000_split_056.html
part0000_split_057.html
part0000_split_058.html
part0000_split_059.html
part0000_split_060.html
part0000_split_061.html
part0000_split_062.html
part0000_split_063.html
part0000_split_064.html
part0000_split_065.html
part0000_split_066.html
part0000_split_067.html
part0000_split_068.html
part0000_split_069.html
part0000_split_070.html
part0000_split_071.html
part0000_split_072.html
part0000_split_073.html
part0000_split_074.html
part0000_split_075.html
part0000_split_076.html
part0000_split_077.html
part0000_split_078.html
part0000_split_079.html
part0000_split_080.html
part0000_split_081.html
part0000_split_082.html
part0000_split_083.html
part0000_split_084.html
part0000_split_085.html
part0000_split_086.html
part0000_split_087.html
part0000_split_088.html
part0000_split_089.html
part0000_split_090.html
part0000_split_091.html
part0000_split_092.html
part0000_split_093.html
part0000_split_094.html
part0000_split_095.html
part0000_split_096.html
part0000_split_097.html
part0000_split_098.html
part0000_split_099.html
part0000_split_100.html
part0000_split_101.html
part0000_split_102.html
part0000_split_103.html
part0000_split_104.html
part0000_split_105.html
part0000_split_106.html
part0000_split_107.html
part0000_split_108.html
part0000_split_109.html
part0000_split_110.html
part0000_split_111.html
part0000_split_112.html
part0000_split_113.html
part0000_split_114.html
part0000_split_115.html
part0000_split_116.html
part0000_split_117.html
part0000_split_118.html
part0000_split_119.html
part0000_split_120.html
part0000_split_121.html
part0000_split_122.html
part0000_split_123.html
part0000_split_124.html
part0000_split_125.html
part0000_split_126.html
part0000_split_127.html
part0000_split_128.html
part0000_split_129.html
part0000_split_130.html
part0000_split_131.html
part0000_split_132.html
part0000_split_133.html
part0000_split_134.html
part0000_split_135.html
part0000_split_136.html
part0000_split_137.html
part0000_split_138.html
part0000_split_139.html