Thursday, August 16, 2007

Call-by-reference in Java; StringBuilder

Objects are always passed by reference to Java functions. Thus, any change to the objects are reflected after function return. Of course, changes to the object referencs (the variables themselves) are lost on return. This does not apply to primitives (int, boolean, float). Also, several classes, String, Integer, Double, Boolean, are immutables; thus, it is impossible to change them after construction. Thus, they cannot be used for call-by-reference (demonstration). StringBuffer, on the other hand, can nicely demonstrate this:

static void changeStringBuffer(StringBuffer sb) {
  sb.append(" and some more");
}
public static void main(String[] args) {
  StringBuffer sb("A text");
  changeStringBuffer(sb);
  // this one gives "A text and some more"
  System.out.println(sb.toString());
}
In place of StringBuffer, often the simpler an not-thread-safe class StringBuilder can be used. Swapping, though, does not work:
public static void swap(StringBuffer a, StringBuffer b) {
  StringBuffer c = a;
  a = b;
  b = c;
}
does not really do anything. BTW ... when concatenating Strings, it is better to use StringBuilder and .append, as
String s;
for (.;.;.) s += something; 
is pretty inefficient; for each +=, the String's content needs to be copied into a new instance that has a bit more space at the end for "something". Results in O(n^2) "efficiency", while StringBuilder only needs to get more memory when an internal limit is reached.

No comments: