1

I have figured out the followings:

  1. 1 + 2 + "3" results in "33"
  2. 1 + 2 + '3' results in 54 which is an integer.

I can't understand which casting rules Java follows while evaluating expressions.

To me, it seems like Java does Widening Casting to the nearest type in the type hierarchy. In the first case, int -> string takes place and char -> int in the latter case.

Can someone please give the formal rule that Java uses in these cases? Thanks!

  • 1
    you are not adding string you are adding character to int value, take a look at the value of character 1 here https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html which is 49, i.e it start from 49 so for 3 becomes 53 and you addition makes as ` 2 + 1 + 51 = 54` – silentsudo Jun 10 '20 at 16:08

4 Answers4

6

+ is left-associative, so

a + b + c

is always evaluated as

(a + b) + c

The rules at play in deciding how the + operator is applied are JLS 15.18:

  • If just one operand to + is a String, the other operand is converted to a string, and then string concatenation is used.
  • If both operands are numbers (or convertible to numbers by unboxing), the operands undergo binary numeric promotion, and then they are numerically added.
  • Otherwise, compiler error.

Taking your examples in turn:


(1 + 2) + "3"

first evaluates (1 + 2), and they're both numbers, so numeric addition applies: they're the same type, so they remain ints after binary numeric promotion, yielding 3.

3 + "3"

The second operand is a String, so the first is converted to a String, and then the two strings are concatenated:

"33"

(1 + 2) + '3'

Same thing happens for the (1+2) = 3.

'3' is a char, which is a numeric type, so 3 and '3' undergo binary numeric promotion to int, and then are numerically added. (int) '3' == 51, so 3 + 51 = 54.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
5
  • 1 + 2 + "3

Here you're adding 1 + 2 = 3 then concatenating that result 3 with the String "3" so you will get a String value of "33"
It's like (1+2)+"3" in parenthesis will return an int value (result of sum operation) and will be concatenated with the String "3"

See here about String concatenation in Java


  • 1 + 2 + '3'

Here you are adding 1 + 2 + (ASCII code of '3') which is 51 so it is 1 + 2 + 51 = 54 here your result will be of type int

Bashir
  • 2,057
  • 5
  • 19
  • 44
  • 1
    Why Java does in that way? In the first case, why it's not casting "3" to int and adding three integers? – Meylis Matiyev Jun 10 '20 at 16:09
  • you have to tell JAVA that you want to cast it using `Integer.parseInt("3") ` (this will return an int value) java is not that smart to guess that you want to cast `"3" ` to `int` instead of applying concatenation which done with the `+` symbol as well – Bashir Jun 10 '20 at 16:12
3

A few rules are mixing together here to produce these results:

  1. operator precedence: + is resolved 'left to right'. See JLS 15.18.

  2. a char is in fact numeric. It's an unsigned 16-bit number. The only reason they tend to look like chars is that the implementation of, say, System.out.println(someChar) is to print the character, but that's due to how that println method is defined. The language is pretty specific; chars are numbers. Therefore, 'a' + 'b' is not "ab", it's 195. See JLS 4.2.1 that says 'char' is numeric.

  3. int math 'widens' automatically to ints, even if the components are smaller than that. So, 'a' + 'b' is an expression of type int and not char. See JLS 5.6.2 as well back to JLS 15.18, which says that numeric addition is an operator that applies 'binary numeric promotion'.

  4. Finally, string concatenation is found in JLS 15.18.1. This says that before even trying to figure out what + means, the compiler already knows the types of each expression that is part of a + expression. Note that a + b + c is just shorthand for (a + b) + c (that's what 'left associative means', so as far as the spec is concerned, a + operation is always between 2 things, never more than 2. If either 'side' (so the 'a' or the 'b') is a string, then the compiler interprets the + to mean: String concat. Otherwise, it doesn't.

  5. Strings in java are not primitive, and not numeric at all. You cannot 'cast' a string to an int. try it: int x = (int) "5"; does not work. 'cast' is usually a confusing name. I suggest you use 'type conversion', 'type assertion', and 'typecheck': 3 completely and utterly unrelated java concepts that all look the same. type conversion is: (int) somePrimitive - the thing in the parens is a primitive type. This converts things. type check is: (String) y; - this checks if y is in fact 'instanceof String'. If it is not, this throws a classcast exception. If it is, nothing happens, but the compiler will treat the type of the expression as String. It never converts, ever. type assertion is when generics are involved, and is solely a way to tell the compiler to make assumptions, and always gets you a compiler warning because it's weird and you shouldn't do it. This one is: (List<String>) someList.

Put these 5 together and you can explain all of these.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
1

The first expression will increment the 1 + 2 and concatenate to string "3", so the output "33"

1 + 2 + "3"

The second expression will increment 1 + 2 plus converting character '3' into ASCII value decimal = 51 value because you plus to an integer, so the output 54

1 + 2 + '3'

Review ASCII table

0xh3xa
  • 4,801
  • 2
  • 14
  • 28