Instructional Material: Passing Reference Parameters

Printer-friendly version

In the lesson on passing parameters we learned that parameters are passed by value, that is, a copy of the calling code's value is given to the method for it's internal use only. Reference (object) parameters are passed the same way but there is an important distinction to make in how reference parameters (objects) are used in methods.

For this lesson, we are going to use the String object and a new object called StringBuffer. StringBuffer is part of the standard Java API library. We will use String and StringBuffer to illustrate show Java manages object instances and reference variables.

 String objects are immutable, meaning that once they are created they can't be changed. So if we do this:

The first statement created a String object instance with the value "abc". Java allocates computer memory and places a String object containing the characters abc into that memory and places a reference (pointer) to that memory location in the variable myString. The second statement creates a new String object instance with the value "xyz" and places a reference to that new object in the same variable, myString. At this point the reference (pointer) to the original object containing "abc" is now no longer available to us. "abc" still exists in memory but we overlayed the reference to "abc" with a reference to "xyz". The String object "abc" is now orphaned, meaning it no longer is connected to a variable in our program and will be discarded by Java. This is called garbage collection.

Note that the String object has no methods that change it's contents. Strings are modified by making a new String object from the old one. Here is another example:

Here again, we did not modify the string "abc" with the second statement. A new string is created containing the characters myString references, "abc" in this case, and concatenates the string "xyz" to create a new string containing "abcxyz" and a reference to this new string is stored in myString. The original string containing "abc" is no longer referenced by this code and will be garbage collected.

Now the StringBuffer class does provide methods to change it's contents without creating a new object. So if we do this:

The first statement creates a new StringBuffer object instance and places "abc" into it. The second statement calls a method on the StringBuffer object that adds "xyz" to the "abc" already inside the StringBuffer object instance without creating a new instance. When done, mySB is still a reference to the same StringBuffer object which now contains "abcxyz".

So with all of that out of the way we can discuss the nuances of using reference parameters in a method.

Consider this example:

The intent of the method is to append "xyz" to whatever is in the String str. After the call to myMethod(), what is in the String myStr? The answer is "abc". Why? The parameter myStr is passed as a copy and placed into the method variable str. In the method, we change the contents of str. Str now points to a new String object instance containing "abcxyz". However, this new String object instance reference is not passed back to the calling code. myStr still points to "abc". Now consider this example:

After the call to myMethod1(), what does mySB contain? The answer is "abcxyz". Why? Because we called a method on the mySB object instance using the copy of mySB passed into the method's sb variable. This means that sb also references or points to the same object instance as mySB. With the StringBuffer object's append method, we change the internal state of the object instance jointly pointed to by sb and mySB.

After the call to myMethod2(), what does mySB contain? The answer is still "abcxyz". Why? Because we created a new StringBuffer object instance containing "xyz" and stored the reference to it in sb. For the rest of the method sb contains a reference to "xyz". Since we changed the object instance that sb points to, the method lost its pointer to mySB and can't reference it after that point. Note that at the end of the method sb, which contains "123456", will be released since variables created in a method only exist while that method is executing.

As a final point, in our first example the method wanted to append "xyz" to whatever string was passed into it, but it does not change the string that was passed in. Here is how you could fix that method:

Here the method concatenates the two strings using the + operator and creates a new string with it's reference deposited into str. The method then returns this new string reference and the calling code replaces the original string reference with the returned string reference and so myStr ends up pointing to the string instance "abcxyz".

A final note about garbage collection. In the last example, str will go out of scope when the method ends. You might think the new string pointed to by str would be orphaned and then garbage collected. However, since a reference to the actual string object instance in memory was passed back to the calling program and placed into myStr, the string object is not orphaned and will continue to exist. When a reference to an object instance is stored in a variable, the JVM keeps track of that by incrementing the object instance's reference count. When a variable that references an object goes out of scope or the variable has something new stored in it, the JVM decrements the object instance reference count. This is how the JVM knows when an object instance is orphaned, when its reference count goes to zero (no variable is pointing to it). When no variable is pointing to an object instance in memory, that object instance is no longer accessible and the memory can be released.

Here are the examples on CodingGround.

 

Material Type: 
Lecture/Presentation
Education Level: 
HW Platform: 
SW Platform: 
Interactivity Style: 
Audience: