<div dir="ltr">Isn't Louis's proposed behavior equivalent to saying "the rightmost concatenation threw an OOME" instead of "some concatenation in the middle threw an OOME"? <div><br></div><div>It's true that the intermediate String concatenations haven't occurred at that point, but in the JDK's current implementation, that's true, too: the concatenations that have occurred at that point are StringBuilder ones, not String ones.  If any of the append operations throws an OOME, no Strings have been created at all, either in Louis's implementation or in the JDK's.<div><br></div><div>Ultimately, isn't this a quality of implementation issue?  And if so, isn't it a quality of implementation issue that doesn't provide any additional quality?  I can't imagine code whose semantics relies on this, and if they do, they are relying on something implementation-dependent.</div><div><br></div><div><div>Jeremy</div></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Mar 11, 2015 at 6:13 PM, Alex Buckley <span dir="ltr"><<a href="mailto:alex.buckley@oracle.com" target="_blank">alex.buckley@oracle.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On 3/11/2015 2:01 PM, Louis Wasserman wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
So for example, "foo" + myInt + myString + "bar" + myObj would be<br>
compiled to the equivalent of<br>
<br>
int myIntTmp = myInt;<br>
String myStringTmp = String.valueOf(myString); // defend against null<br>
String myObjTmp = String.valueOf(String.valueOf(<u></u>myObj)); // defend<br>
against evil toString implementations returning null<br>
<br>
return new StringBuilder(<br>
      17 // length of "foo" (3) + max length of myInt (11) + length of<br>
"bar" (3)<br>
      + myStringTmp.length()<br>
      + myObjTmp.length())<br>
    .append("foo")<br>
    .append(myIntTmp)<br>
    .append(myStringTmp)<br>
    .append("bar")<br>
    .append(myObjTmp)<br>
    .toString();<br>
<br>
As far as language constraints go, the JLS is (apparently deliberately)<br>
vague about how string concatenation is implemented.  "An implementation<br>
may choose to perform conversion and concatenation in one step to avoid<br>
creating and then discarding an intermediate String object. To increase<br>
the performance of repeated string concatenation, a Java compiler may<br>
use the StringBuffer class or a similar technique to reduce the number<br>
of intermediate String objects that are created by evaluation of an<br>
expression."  We see no reason this approach would not qualify as a<br>
"similar technique."<br>
</blockquote>
<br></div></div>
The really key property of the string concatenation operator is left-associativity. Later subexpressions must not be evaluated until earlier subexpressions have been successfully evaluated AND concatenated. Consider this expression:<br>
<br>
  "foo" + m() + n()<br>
<br>
which JLS8 15.8 specifies to mean:<br>
<br>
  ("foo" + m()) + n()<br>
<br>
We know from JLS8 15.6 that if m() throws, then foo+m() throws, and n() will never be evaluated.<br>
<br>
Happily, your translation doesn't appear to catch and swallow exceptions when eagerly evaluating each subexpression in turn, so I believe you won't evaluate n() if m() already threw.<br>
<br>
Unhappily, a call to append(..) can in general fail with OutOfMemoryError. (I'm not talking about asynchronous exceptions in general, but rather the sense that append(..) manipulates the heap so an OOME is at least plausible.) In the OpenJDK implementation, if blah.append(m()) fails with OOME, then n() hasn't been evaluated yet -- that's "real" left-associativity. In the proposed implementation, it's possible that more memory is available when evaluating m() and n() upfront than at the time of an append call, so n() is evaluated even if append(<<tmp result of m()>>) fails -- that's not left-associative.<br>
<br>
Perhaps you can set my mind at ease that append(..) can't fail with OOME?<span class="HOEnZb"><font color="#888888"><br>
<br>
Alex<br>
</font></span></blockquote></div><br></div>