I've been reading Java Puzzlers by Bloch and Gafter and got to the puzzle 10 (Tweedledee). The essence of this puzzle is to
provide declarations for the variables
x
andi
such that this is a legal statement:x = x + i;
but this is not:
x += i;
The solution to this looks, according to the book, like this:
Object x = "Buy ";
String i = "Effective Java!";
The book claims that in the +=
operator the right-hand expression can be of any type only if the left-hand expression has type String
. However, I tried to run this code, and it compiled and ran without any problems.
Then I dug into the Java Language Specification. Section 15.26.2 talks about two cases: when the left-hand expression is an array access expression and when it's not. If the left-hand operand expression is not an array access expression, then JLS doesn't say anything about the left-hand expression being a String. When it is, this part appllies:
If T is a reference type, then it must be String. Because class String is a final class, S must also be String. Therefore the run-time check that is sometimes required for the simple assignment operator is never required for a compound assignment operator.
❖ The saved value of the array component and the value of the right-hand operand are used to perform the binary operation (string concatenation) indicated by the compound assignment operator (which is necessarily +=). If this operation completes abruptly, then the assignment expression completes abruptly for the same reason and no assignment occurs.
T here is the type of the left-hand operand as determined at compile-time, and S is the selected array component. So I thought that I would modify my code into this:
Object[] x = {new Object()};
String i = "Effective Java!";
x[0] += i;
But even this code compiles and runs without any problems even though new Object()
is not even remotely a String
.
Why is this happening? Does this mean that Java compiler deviates from the JLS? And is it still possible to somehow solve the original puzzle?
toString
to print to stdout/stderr? – Aperiodicx += i;
is valid, butx = x + i;
is not. – Spirox += i
and noti += x
? I mean (String) += (Object) will compile easily, when (Object) += (String) will not compile. – Acrobaticjava.lang.Object@5a4b4b50Effective Java!
. So concatenation happens nicely. – Harwill