Next: Java- last part, comparators
Up: Part 1: Crash Course
Previous: Sets vs. Maps
Every semester a new group of students get cought up by the same thing in Java. They
start out hearing "Java is always pass by reference" and they do silly looking things
like the following:
void foo(String t)
{
t = new String("World");
}
String s = new String("Hello");
foo(s);
System.out.print(s); //prints "Hello". Why didn't it change?
In true pass by reference C++ this would have worked. But what is happening is
not really pass by reference, it is pass by value, except what is being passed
is a pointer. If you were to tranfer the above to C++ it would look like:
void foo(String *t)
{
t = new String("World");
}
String *s = new String("Hello");
foo(s);
cout<<*s<<endl; //prints "Hello". Hopefully obvious why
You can see in the second example that t is only a local copy of s. If you alter the
value t is pointing at then s will see the change. However, if you point t at something
else s will never know. In this example there is actually no way for foo to change s, since
java Strings are immutable after creation. An error less obvious than the above is:
void foo(String t)
{
t = t+"World";
}
This looks like concatenation, not reallocation, but that '+' operator actually allocates
a new String. The above is actually just a shortcut in java for:
void foo(String t)
{
StringBuffer temp = new StringBuffer();
temp.append(t);
temp.append("World");
t = temp.toString();
}
It's important to realize what's going on in the background! Of course in the above
example, foo still doesn't change t, but what you could do instead is:
void foo(StringBuffer t)
{
t.append("World");
}
This time, since t always points to the same place the original value really is modified.
In java "pass by reference" as C++ programmers tend to think of it always requires some kind
of wrapper. In the last example, StringBuffer is a wrapper for a dynamically sized
character array. There is a quick and dirty hack to get a similar effect without building
and entire class wrapper, pass a 1 element array instead:
void foo(String[] t)
{
t[0] = new String("World");
}
String s[]=new String[1];
s[0] = new String("Hello");
foo(s); //s[0]= "World"
This works for a similar reason. t points to the same array in memory that s does.
When an element of the array is updated by t, s will see the change as well. This ends
my FYI on pass by reference, try not to get cought up by this common error :)
Next: Java- last part, comparators
Up: Part 1: Crash Course
Previous: Sets vs. Maps
MM Hugue
2004-07-15