String plus Char - what is happening?
String literals are char const[N]
(decays to char const *
), and char
is a small range integer type. You're doing pointer arithmetic.
What is happening when I add a char and a String in Java?
You precisely named the reason why using the +
operator for string concatenation can be seen as a historical design mistake. Providing a builtin concatenation operator is not wrong, but it should not have been the plus operator.
Besides the confusion about different behavior, e.g. for 'a'+'b'
and ""+'a'+'b'
, the plus operator is normally expected to be commutative, i.e. a + b
has the same result as b + a
, which doesn’t hold for string concatenation. Further, the operator precedence can lead to surprises.
The behavior is precisely specified (JLS §15.18.1):
15.18.1. String Concatenation Operator +
If only one operand expression is of type
String
, then string conversion (§5.1.11) is performed on the other operand to produce a string at run time.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.
This definition links to §5.1.11:
5.1.11. String Conversion
Any type may be converted to type
String
by string conversion.A value
x
of primitive typeT
is first converted to a reference value as if by giving it as an argument to an appropriate class instance creation expression (§15.9):
If
T
isboolean
, then usenew Boolean(x)
.If
T
ischar
, then usenew Character(x)
.If
T
isbyte
,short
, orint
, then usenew Integer(x)
.If
T
islong
, then usenew Long(x)
.If
T
isfloat
, then usenew Float(x)
.If
T
isdouble
, then usenew Double(x)
.This reference value is then converted to type
String
by string conversion.Now only reference values need to be considered:
If the reference is
null
, it is converted to the string "null
" (four ASCII charactersn
,u
,l
,l
).Otherwise, the conversion is performed as if by an invocation of the
toString
method of the referenced object with no arguments; but if the result of invoking thetoString
method isnull
, then the string "null
" is used instead.
(The spec’s formatting truly is "null
" rather than "null"
)
So the behavior of String foo = 'a' + "bee";
is specified to be as-if you’ve written String foo = new Character('a').toString() + "bee";
But the cited §15.18.1 continues with:
The
String
object is newly created (§12.5) unless the expression is a constant expression (§15.28).An implementation may choose to perform conversion and concatenation in one step to avoid creating and then discarding an intermediate
String
object. To increase the performance of repeated string concatenation, a Java compiler may use theStringBuffer
class or a similar technique to reduce the number of intermediateString
objects that are created by evaluation of an expression.For primitive types, an implementation may also optimize away the creation of a wrapper object by converting directly from a primitive type to a string.
So for your specific example, 'a' + "bee"
, the actual behavior of
String foo = 'a' + "bee";
will be
String foo = "abee";
without any additional operations at runtime, because it is a compile-time constant.
If one of the operands is not a compile-time constant, like
char c = 'a';
String foo = c + "bee";
The optimized variant, as used by most if not all compilers from Java 5 to Java 8 (inclusive), is
char c = 'a';
String foo = new StringBuilder().append(c).append("bee").toString();
See also this answer. Starting with Java 9, a different approach will be used.
The resulting behavior will always be like specified.
why does a char + another char = a weird number
+
of two char
is arithmetic addition, not string concatenation. You have to do something like "" + ca + cb
, or use String.valueOf
and Character.toString
methods to ensure that at least one of the operands of +
is a String
for the operator to be string concatenation.
JLS 15.18 Additive Operators
If the type of either operand of a
+
operator isString
, then the operation is string concatenation.Otherwise, the type of each of the operands of the
+
operator must be a type that is convertible to a primitive numeric type, or a compile-time error occurs.
As to why you're getting 195, it's because in ASCII, 'a' = 97
and 'b' = 98
, and 97 + 98 = 195
.
This performs basic int
and char
casting.
char ch = 'a';
int i = (int) ch;
System.out.println(i); // prints "97"
ch = (char) 99;
System.out.println(ch); // prints "c"
This ignores the issue of character encoding schemes (which a beginner should not worry about... yet!).
As a note, Josh Bloch noted that it is rather unfortunate that +
is overloaded for both string concatenation and integer addition ("It may have been a mistake to overload the + operator for string concatenation." -- Java Puzzlers, Puzzle 11: The Last Laugh). A lot of this kinds of confusion could've been easily avoided by having a different token for string concatenation.
See also
- Is concatenating with an empty string to do a string conversion really that bad?
How to append a char to a std::string?
y += d;
I would use +=
operator instead of named functions.
Why does char concatenation returns int sum?
The difference is in the way the concatenations are constructed.
First: res += str.charAt(0) + str.charAt(2);
Here, the two char
values are added together first. Binary numeric promotion occurs (JLS, Section 5.6.2).
Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:
If either operand is of type double, the other is converted to double.
Otherwise, if either operand is of type float, the other is converted to float.
Otherwise, if either operand is of type long, the other is converted to long.
Otherwise, both operands are converted to type int.
That means that the values are promoted to int
, creating your 196
. That is then added to str
, appending "196"
.
Second: res = res + str.charAt(0) + str.charAt(2);
Here, the res + str.charAt(0)
is performed first, and a String
plus a char
appends the char
(via String Conversion, JLS 15.18.1, resulting in a new String
.
If only one operand expression is of type String, then string conversion (§5.1.11) is performed on the other operand to produce a string at run time.
Then, the second char
is appended similarly.
If you were to say
res = res + (str.charAt(0) + str.charAt(2));
then the result would be the same (appending the 196
) as with +=
.
Append Char To String in C?
char* str = "blablabla";
You should not modify this string at all. It resides in implementation defined read only region. Modifying it causes Undefined Behavior.
You need a char array not a string literal.
Good Read:
What is the difference between char a[] = "string"; and char *p = "string";
Why can I add characters to strings but not characters to characters?
It's because String + Char = String, similar to how an int + double = double.
Char + Char is int despite what the other answers tell you.
String s = 1; // compilation error due to mismatched types.
Your working code is (String+Char)+Char. If you had done this: String+(Char+Char) you would get a number in your string. Example:
System.out.println("" + ('x' + 'x')); // prints 240
System.out.println(("" + 'x') + 'x'); // prints xx - this is the same as leaving out the ( ).
In Java, is the result of the addition of two chars an int or a char?
The result of adding Java chars, shorts, or bytes is an int:
Java Language Specification on Binary Numeric Promotion:
- If any of the operands is of a reference type, unboxing conversion
(§5.1.8) is performed. Then:- If either operand is of type double, the
other is converted to double.- Otherwise, if either operand is of type
float, the other is converted to float.- Otherwise, if either operand
is of type long, the other is converted to long.- Otherwise, both
operands are converted to type int.
But note what it says about compound assignment operators (like +=):
The result of the binary operation is converted to the type of the left-hand variable ... and the result of the conversion is stored into the variable.
For example:
char x = 1, y = 2;
x = x + y; // compile error: "possible loss of precision (found int, required char)"
x = (char)(x + y); // explicit cast back to char; OK
x += y; // compound operation-assignment; also OK
One way you can find out the type of the result, in general, is to cast it to an Object and ask it what class it is:
System.out.println(((Object)('a' + 'b')).getClass());
// outputs: class java.lang.Integer
If you're interested in performance, note that the Java bytecode doesn't even have dedicated instructions for arithmetic with the smaller data types. For example, for adding, there are instructions iadd
(for ints), ladd
(for longs), fadd
(for floats), dadd
(for doubles), and that's it. To simulate x += y
with the smaller types, the compiler will use iadd
and then zero the upper bytes of the int using an instruction like i2c
("int to char"). If the native CPU has dedicated instructions for 1-byte or 2-byte data, it's up to the Java virtual machine to optimize for that at run time.
If you want to concatenate characters as a String rather than interpreting them as a numeric type, there are lots of ways to do that. The easiest is adding an empty String to the expression, because adding a char and a String results in a String. All of these expressions result in the String "ab"
:
'a' + "" + 'b'
"" + 'a' + 'b'
(this works because"" + 'a'
is evaluated first; if the""
were at the end instead you would get"195"
)new String(new char[] { 'a', 'b' })
new StringBuilder().append('a').append('b').toString()
String.format("%c%c", 'a', 'b')
char + String giving strange result
That's the ascii sum of the characters:
For your first case, i
has ascii 105
and k
has ascii 107
so their sum is 212
.
Try str.subString(0, 2)
instead of adding the char
variables.
Related Topics
C++11: "Narrowing Conversion Inside { }" with Modulus
Getting Input from User Using Cin
How to Tell If a Class/Struct Has No Data Members
What Are Some Tricks I Can Use with MACros
Generate a Plane with Triangle Strips
Compiling Code Containing Dynamic Parallelism Fails
What Are These Seemingly-Useless Callq Instructions in My X86 Object Files For
How to Implement Interfaces in C++
How to Throw Std::Exceptions with Variable Messages
How to Use Gpu::Stream in Opencv
Error: Expression Must Have a Class Type
C++ If Else If Not Working Properly
Easiest Way to Flip a Boolean Value
How to Set Pointer to a Memory to Null Using Memset
Why Can't I Assign an Array Variable Directly to Another Array Variable with the '=' Operator
C++ Get Handle of Open Sockets of a Program