Here what you are overlooking is the fact that Java deals differently with String object from any other object.
In Java String is "immutable".
When we say "immutable" it means once an object is created you cannot change it, thus for String, once it has created you cannot change its value.
Thus whenever code tries to change the string object, JVM creates new String object with same value and will perform operation on that.
So at the line :
s1 = s1 + "ranch"; return s1;
JVM will create new String object "java" will point s1 to that and will add the "ranch" string to get again new String object with value "javaranch" and make s1 point to this,
thus s2 will point to "javaranch" object, in the doString method
and s1 continues to point at "java".
However in case of array object or any other object, when you change object pointed by reference a1, it actually changing the actual object.
In java you pass object reference by value,
Thus at line:
public long[] changeLong(long[] a1) {...}
a1 is a new reference variable of type array of long pointing to the same long array object in the doLong object. and here whatever you change will change the original array object as it is NOT immutable.
I Hope this will help you..
K&B book nicely explained the java String object.