The concatenation of chars to form a string gives different results

The result of the following expression

ret + str.charAt(i) + str.charAt(i); 

is the result of String concatenation. The Java language specification states

The result of string concatenation is a reference to a String object that is the concatenation of the two operand strings. The characters of the left-hand operand precede the characters of the right-hand operand in the newly created string.

The result of

str.charAt(i) + str.charAt(i); 

is the result of the additive operator applied to two numeric types. The Java language specification states

The binary + operator performs addition when applied to two operands of numeric type, producing the sum of the operands. [...] The type of an additive expression on numeric operands is the promoted type of its operands.

In which case

str.charAt(i) + str.charAt(i); 

becomes an int holding the sum of the two char values. That is then concatenated to ret.


You might also want to know this about the compound assignment expression +=

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

In other words

ret += str.charAt(i) + str.charAt(i);

is equivalent to

ret = (String) ((ret) + (str.charAt(i) + str.charAt(i)));
                      |                ^ integer addition
                      |
                      ^ string concatenation

In your first example, you are explicitly adding a String as the first term. That forces the second and third term to also be promoted to String(s). In the second case, you are adding two characters (which are then appended to the String) - it does not promote to a String until the assignment. You could have been explicit, by using Character.toString() or String.valueOf() like so

ret += Character.toString(str.charAt(i)) + String.valueOf(str.charAt(i));

The First Example

From the semantics, I'd say we're looking at arithmetic promotion at work. Note the first example:

String + char + char

Due to arithmetic promotion, those two char values are promoted to String values, so the types become:

String + String + String

The + is overloaded, to perform concatenation because all operands are of type String.

The Second Example

In the second example, as with all assignments, we evaluate the right hand side of the = operator first, and what do we have?

char + char

The char is interpreted as its numerical value, because there is no String to cause promotion, and we have a numerical addition, which is then appended to the String.

Extra Reading

Some notes on arithmetic promotion can be found here.

Some notes on expression evaluation can be found here.


From the Java specification:

15.26.2. Compound Assignment Operators

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

So the += operator has a built-in cast to the destination type.

In contrast, the clause for simple assignment says:

15.26.1. Simple Assignment Operator =

A compile-time error occurs if the type of the right-hand operand cannot be converted to the type of the variable by assignment conversion (§5.2).

Here,

 ret = ret + str.charAt(i) + str.charAt(i);

is treated as a string concatination.

And

ret += str.charAt(i) + str.charAt(i);

is treated as aditive operation.