Java += operator on String with charAt() methods results in char addition
Asked Answered
H

3

5

I'm working through the problems on Codingbat.com and bumped into the fact that for the += operator, a += b isn't necessarily exactly equal to a = a + b. This is well known and has been discussed on SO before, but I bumped into something strange happening when using the charAt() method combined with the above syntax that I can't make sense of.

Say I have two variables:

String str    = "The";
String result = "";

I want to add the first letter in "str" two times to "result". One way of doing this is to:

result = result + str.charAt(0) + str.charAt(0);

which results in result = "TT".

However, if I use the += operator, e.g.:

result += str.charAt(0) + str.charAt(0);

I get result = "168". Clearly character addition has taken place (ASCII code for 'T' is 84, 84*2 = 168).

I'm wondering what is actually going on in the first case using the += operator. According to the docs on assignment operators: E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)). So I would expect the latter expression to output "168" just like using the += operator did. But the following outputs "TT" correctly, and not "168":

result = (String)(result + str.charAt(0) + str.charAt(0));

Have I just misunderstood the documentation? I also found an answer on SO that suggests that str1 += str2 is equivalent to:

str1 = new StringBuilder().append(str1).append(str2).toString();

But evaluating the following:

result = new StringBuilder().append(str.charAt(0)).append(str.charAt(0)).toString();

Still results in "TT", not "168".

Sorry for the long post! I'm just curious at what actually is happening when using charAt() in combination with a String and +=, because the two "equivalents" I've found (if I've translated them from two to three terms correctly) does not produce the same result.

Heliacal answered 24/7, 2014 at 15:54 Comment(4)
Is it sufficient to say "Don't do that"? If not, look at operator precedence.Rockrose
No, I can easily surpass the problem, but I wanted to learn from it too. Thanks for the link! I always forget to think of operator precedence.Heliacal
It's kind of like the Spanish Inquisition.Rockrose
Nobody expects the Spanish Inquisition!Heliacal
M
6

As you stated in your question E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)). So the line

result += str.charAt(0) + str.charAt(0);

is equivalent to

result = (String) ((result) + (str.charAt(0) + str.charAt(0)));

(Note the parentheses around the char addition, they are important)

This will evaluate to

result = (String) (("") + ('T' + 'T'));
result = (String) (("") + (168));
result = (String) ("168");
result = "168";

whereas without parentheses you get

result = (String) ("" + 'T' + 'T');
result = (String) ("T" + 'T');
result = (String) ("TT");
result = "TT";
Matroclinous answered 24/7, 2014 at 16:0 Comment(0)
N
7
result = result + str.charAt(0) + str.charAt(0);

result is a string, so the first + performs string concatenation, producing another string. The second +, by the same logic, will also perform string concatenation. This gives the desired result.

result += str.charAt(0) + str.charAt(0);

The right-hand side, str.charAt(0) + str.charAt(0), is evaluated first. Now, you're adding two characters, which works like simple integer addition, adding the ASCII values. We then append this result (an int -- 84 in this case) to result, which is what you see.

char c = 'T';
System.out.println(c + c);
168

The underlying difference here is just the order in which things are evaluated.

Negotiant answered 24/7, 2014 at 15:58 Comment(0)
M
6

As you stated in your question E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)). So the line

result += str.charAt(0) + str.charAt(0);

is equivalent to

result = (String) ((result) + (str.charAt(0) + str.charAt(0)));

(Note the parentheses around the char addition, they are important)

This will evaluate to

result = (String) (("") + ('T' + 'T'));
result = (String) (("") + (168));
result = (String) ("168");
result = "168";

whereas without parentheses you get

result = (String) ("" + 'T' + 'T');
result = (String) ("T" + 'T');
result = (String) ("TT");
result = "TT";
Matroclinous answered 24/7, 2014 at 16:0 Comment(0)
M
2
str.charAt(0) + str.charAt(0)

is evaluated as a whole before the assignment += takes place.

charAt returns a char, on which addition is defined like on integers. Therefore, this is the same as :

result = result + (str.charAt(0) + str.charAt(0));
Mallette answered 24/7, 2014 at 15:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.