Java Pitfall: pass by value? by reference?
I ran into this pitfall trying to print out all valid combinations of n pair of parenthesis. The recursive code I wrote was pretty straightforward:
However, instead of giving me "()(), (())", it keeps giving me "(()), (()()". l and r seems to behave just the way I want during recursion, so it's gotta be the only other parameter that's screwing up the recursion: str. It indeed is.
Correct code:
str+='('; str+=')';
Make the code work is easy. Understand what's happening here takes a little more effort.
Back to Java 101:
All strings are instances of String class. Java pass by value for primitive types and reference for objects.
The incorrect "(()()" is caused by Java passing by reference, while str still possess the "((" value from last recursion. My brain tends to go nuts trying to imagine full recursion cycles, and using reference during recursion is only gonna make it worse. Therefore, always try pass by value for recursion.
BTW: Strings are constants. All strings are initialized at create time and can't be changed afterwards. When we do str += ')', what's happening behind the scene is:
I ran into this pitfall trying to print out all valid combinations of n pair of parenthesis. The recursive code I wrote was pretty straightforward:
public static void recurPrint(int l, int r, String str) {
if (l==0 && r==0) {
System.out.println(str);
}
else {
if(l>0) {
str+='(';
recurPrint(l-1, r, str);
}
if (r>0) {
str+=')';
recurPrint(l, r-1, str);
}
}
}
public static void main(String[] args) {
recurPrint(2,2,"");
}
However, instead of giving me "()(), (())", it keeps giving me "(()), (()()". l and r seems to behave just the way I want during recursion, so it's gotta be the only other parameter that's screwing up the recursion: str. It indeed is.
Correct code:
public static void recurPrint(int l, int r, String str) {
if (l==0 && r==0) {
System.out.println(str);
}
else {
if(l>0) {
recurPrint(l-1, r, str str+'(');
}
if (r>0) {
recurPrint(l, r-1, str str+')');
}
}
}
Make the code work is easy. Understand what's happening here takes a little more effort.
Back to Java 101:
All strings are instances of String class. Java pass by value for primitive types and reference for objects.
The incorrect "(()()" is caused by Java passing by reference, while str still possess the "((" value from last recursion. My brain tends to go nuts trying to imagine full recursion cycles, and using reference during recursion is only gonna make it worse. Therefore, always try pass by value for recursion.
BTW: Strings are constants. All strings are initialized at create time and can't be changed afterwards. When we do str += ')', what's happening behind the scene is:
- a string buffer is created.
- content of str is copied to string buffer
- string buffer is appended with ')'
- new memory chunk is allocated and copied with content of string buffer
- str is assigned with the new memory chunk reference.
