92

When adding 'a' + 'b' it produces 195. Is the output datatype char or int?

orange
  • 5,297
  • 12
  • 50
  • 71
  • 3
    If the type were `char` then the value of `'a' + 'b'` wouldn't be `195` but `'Ã'` – Joren Dec 31 '11 at 22:02
  • 1
    It is 195 on here - http://ideone.com but not in Eclipse. – orange Dec 31 '11 at 22:22
  • 2
    You read that from the Algorithms book lol! I came here because of this exercise exactly ;) – Jack Twain Apr 27 '15 at 08:32
  • [Java (OpenJDK 8) – Try It Online](https://tio.run/##y0osS9TNL0jNy0rJ/v@/oDQpJzNZITknsbhYwTcxM0@hmksBCKDixSWJJUCqLD8zRSEXKKsRXFKUmZceHauQWJRerAlVDALBlcUlqbl6@aUlegVAJSU5eRrqieoK2grqSeqa1hA1@voKhpam@LQoKYF0IOkDaklMIsoSIKmkBNFByJJEkC1KSUpI7oJaUstV@/8/AA) –  Apr 03 '21 at 19:12

8 Answers8

144

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')
Boann
  • 48,794
  • 16
  • 117
  • 146
23

Binary arithmetic operations on char and byte (and short) promote to int -- JLS 5.6.2.

Hot Licks
  • 47,103
  • 17
  • 93
  • 151
7

You may wish to learn the following expressions about char.

char c='A';
int i=c+1;

System.out.println("i = "+i);

This is perfectly valid in Java and returns 66, the corresponding value of the character (Unicode) of c+1.


String temp="";
temp+=c;
System.out.println("temp = "+temp);

This is too valid in Java and the String type variable temp automatically accepts c of type char and produces temp=A on the console.


All the following statements are also valid in Java!

Integer intType=new Integer(c);
System.out.println("intType = "+intType);

Double  doubleType=new Double(c);
System.out.println("doubleType = "+doubleType);

Float floatType=new Float(c);
System.out.println("floatType = "+floatType);

BigDecimal decimalType=new BigDecimal(c);
System.out.println("decimalType = "+decimalType);

Long longType=new Long(c);
System.out.println("longType = "+longType);

Although c is a type of char, it can be supplied with no error in the respective constructors and all of the above statements are treated as valid statements. They produce the following outputs respectively.

intType = 65
doubleType = 65.0
floatType = 65.0
decimalType = 65
longType =65

char is a primitive numeric integral type and as such is subject to all the rules of these beasts including conversions and promotions. You'll want to read up on this, and the JLS is one of the best sources for this: Conversions and Promotions. In particular, read the short bit on "5.1.2 Widening Primitive Conversion".

Lion
  • 18,729
  • 22
  • 80
  • 110
3

The Java compiler can interpret it as either one.

Check it by writing a program and looking for compiler errors:

public static void main(String[] args) {
    int result1 = 'a' + 'b';
    char result2 = 'a' + 'b';
}

If it's a char, then the first line will give me an error and the second one will not. If it's an int, then the opposite will happen.

I compiled it and I got..... NO ERRORS. So Java accepts both.

However, when I printed them, I got:

int: 195

char: Ã

What happens is that when you do:

char result2 = 'a' + 'b'

an implicit conversion is performed (a "primitive narrowing conversion" from int to char).

Community
  • 1
  • 1
eboix
  • 5,113
  • 1
  • 27
  • 38
  • I'm surprised you didn't get a compiler warning in the second case about possible loss of precision due to narrowing. – Hot Licks Dec 31 '11 at 14:54
  • @eboix: you wrote *"the compiler automatically casts to either char or int"* [sic]... Which is not correct because an *int* isn't "casted" to an *int* and going from an *int* to a *char* isn't called a "cast" but a "narrowing primitive conversion" ; ) – TacticalCoder Dec 31 '11 at 14:57
  • Yeah. I was expecting that, too. I had actually written part of my answer about that before making my program, but then I deleted it once I saw that I got no warnings or errors. – eboix Dec 31 '11 at 14:58
  • @eboix: eh eh : ) I would have edited it but I don't have 2 000 reputation points yet, hence my comment instead of an edit ; ) – TacticalCoder Dec 31 '11 at 15:03
  • If you want, @user988052, I can change it back to what it was and you can edit it, getting points. You can still edit it if you have less than 2000 reputation points. The only thing is that the person who made the post has to accept the edit. I'll change it back right now so that you can get the two points that are rightfully yours. – eboix Dec 31 '11 at 15:05
  • Why is implicit conversion performed for this line char result2 = 'a' + 'b'. But not for something like this char x , y = 2,z=3; x = z + y; – matt Aug 05 '17 at 12:35
  • @matt - Because `z + y` is not a *constant expression*. See my answer for a more detailed explanation ... with JLS links. – Stephen C May 24 '20 at 03:40
1

According to the binary promotion rules, if neither of the operands is double, float or long, both are promoted to int. However, I strongly advice against treating char type as numeric, that kind of defeats its purpose.

Sergei Tachenov
  • 24,345
  • 8
  • 57
  • 73
  • 1
    Using `char` as a numeric value is entirely within its purpose, which is why the JLS devotes so much verbiage to such use. – Lew Bloch Jan 06 '17 at 21:17
1

While you have the correct answer already (referenced in the JLS), here's a bit of code to verify that you get an int when adding two chars.

public class CharAdditionTest
{
    public static void main(String args[])
    {
        char a = 'a';
        char b = 'b';

        Object obj = a + b;
        System.out.println(obj.getClass().getName());
    }
}

The output is

java.lang.Integer

Paul
  • 19,704
  • 14
  • 78
  • 96
  • This is not a convincing verification, because you have thrown a boxing conversion into the mix. The types `int` and `Integer` are not the same thing. A more convincing verification is to try to assign `a + b` to an `int` variable or a `char` variable. The latter gives a compilation error that says in effect "you can't assign an `int` to a `char`". – Stephen C May 24 '20 at 02:41
0

char is represented as Unicode values and where Unicode values are represented by \u followed by Hexadecimal values.

As any arithmetic operation on char values promoted to int , so the result of 'a' + 'b' is calculated as

1.) Apply the Unicode values on corresponding char using Unicode Table

2.) Apply the Hexadecimal to Decimal conversion and then perform the operation on Decimal values.

    char        Unicode      Decimal
     a           0061          97
     b           0062          98  +
                              195

Unicode To Decimal Converter

Example

0061

(0*163) + (0*162) + (6*161) + (1*160)

(0*4096) + (0*256) + (6*16) + (1*1)

0 + 0 + 96 + 1 = 97

0062

(0*163) + (0*162) + (6*161) + (2*160)

(0*4096) + (0*256) + (6*16) + (2*1)

0 + 0 + 96 + 2 = 98

Hence 97 + 98 = 195


Example 2

char        Unicode      Decimal
 Ջ           054b         1355
 À           00c0          192 
                      --------
                          1547    +
                          1163    -
                             7    /
                        260160    *
                            11    %
Pavneet_Singh
  • 36,884
  • 5
  • 53
  • 68
  • This is not what the question is asking about. – Stephen C May 24 '20 at 02:37
  • FYI, My detailed response to the above comment has been removed by mods that explained the reason behind the migration of my answer from a deleted post. if my response has been deleted to cover up the SO moderation's flaws then can you at least remove the above comment or indicate the audience somehow so that I don't have to write another comment? questions to SO mods – Pavneet_Singh May 25 '20 at 12:22
  • I stand by my comment. As I replied to you ... but then deleted ... the reason that you posted this Question here does not change the fact that it is 95% off-topic to the question, and 5% repetition of earlier answers. If you wish to save the results of your wasted effort, it would be more appropriate to save it on your hard drive. Or find some other question that it is relevant to. – Stephen C May 25 '20 at 12:30
  • If you have a gripe with the moderators, take it up in meta.stackoverflow.com. And provide evidence. All I am trying to do here is tidy up >>this<< Q&A. – Stephen C May 25 '20 at 12:34
  • I understand your view but cannot understand the fact of ignoring the details of Unicode conversion with examples, as an additional value which might help some readers so I would like to keep this answer(I get it that It's not useful to you and seems off-topic). I avoid meta and similar places as it's not easy to do such things without power or support, which takes lots of time, effort. I prefer to keep my inner peace Sire. – Pavneet_Singh May 25 '20 at 12:57
  • Well leaving a recipe for making fruit cakes might also help the reader too ... if he is trying to bake a fruitcake. If the user is trying to understand the details of Unicode conversion, they will **most likely** have used different search terms and ended up on a different question entirely. For this answer to be useful, it needs to be on >>that<< question. >>This<< question is about the **type** of the result not the value. – Stephen C May 25 '20 at 13:16
  • That will be the same situation(as explained in the initial comment) though Thank you for the suggestion. – Pavneet_Singh May 25 '20 at 13:47
0

While Boann's answer is correct, there is a complication that applies to the case of constant expressions when they appear in assignment contexts.

Consider the following examples:

  char x = 'a' + 'b';   // OK

  char y = 'a';
  char z = y + 'b';     // Compilation error

What is going on? They mean the same thing don't they? And why is it legal to assign an int to a char in the first example?

When a constant expression appears in an assignment context, the Java compiler computes the value of the expression and sees if it is in the range of the type that you are assigning to. If it is, then an implicit narrowing primitive conversion is applied.

  • In the first example, 'a' + 'b' is a constant expression, and its value will fit in a char, so the compiler allows the implicit narrowing of the int expression result to a char.

  • In the second example, y is a variable so y + 'b' is NOT a constant expression. So even though Blind Freddy can see that the value will fit, the compiler does NOT allow any implicit narrowing, and you get a compilation error saying that an int cannot be assigned to a char.

There are some other caveats on when an implicit narrowing primitive conversion is allowed in this context; see JLS 5.2 and JLS 15.28 for the full details.

The latter explains in detail the requirements for a constant expression. It may not be what you may think. (For example, just declaring y as final doesn't help.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216