This piece of code
StringBuilder b1=new StringBuilder("hello"); b1.append(b1.append("!")); System.out.println("b1 = "+b1);
will print
b1 = hello!hello!
because the internal append is executed first and modifies the b1 object; then the outer b1 is evaluated (now it is hello! ), and the same line is added to it. So
- an internal expression is executed
- source object changed
- external expression is executed on the modified object
But now, why does this code throw a NullPointerException ?
StringBuilder s1=null; StringBuilder s2=new StringBuilder("world"); try{s1.append(s1=s2.append("!"));} catch(Exception e){System.out.println(e);} System.out.println("s1 = "+s1+"\ns2 = "+s2+"\n");
and seal
java.lang.NullPointerException s1 = world! s2 = world!
I was expecting the s1 reference to point to the object s2 referencing before executing the external append .
In some ways, the purpose of b1.append("!"); affects the "external" b1 , but s1=s2.append("!") not. I know this because in the first case I change the object, and in the second I change the link, but ... what is the order in which values โโ/ references / methods are evaluated and executed?
Edit
The same thing happens with arrays:
int[] y = { 0, 0, 0 }; try {y[y[0] = 2] = 4;} catch (Exception e) {System.out.println(e);} System.out.println("y = "+Arrays.toString(y)+"\n");
prints
y = [2, 0, 4]
while
int[] x1 = null; int[] x2 = { 1, 2, 3 }; try {x1[(x1=x2)[0]] = 0;} catch (Exception e) {System.out.println(e);} System.out.println("x1 = "+Arrays.toString(x1)+"\nx2 = "+Arrays.toString(x2));
prints
java.lang.NullPointerException x1 = [1, 2, 3] x2 = [1, 2, 3]