Java char addition (char1 = char2 + 10) [duplicate] - java

This question already has answers here:
Why can't you add an int and a char in some cases?
(1 answer)
Java - char, int conversions
(4 answers)
Integer arithmetic in Java with char and integer literal
(6 answers)
Closed 1 year ago.
Why can't i do this?
public class test123 {
public static void main (String [] args) {
char c = 34;
char a = c + 10;
}
}
new to java, so sorry if this question is actually stupid.

When you add numbers, they undergo binary numeric promotion. That is, the operands are widened to allow them to be added.
When you add a char to an int, the char is widened to an int, and the result is an int.
As such, you would have to cast the int back to a char:
char a = (char) (c + 10);
However, even when adding a char to another char, both are widened to int, and the result is again an int, and so cannot be assigned to a char variable. The rules are basically:
If either operand is a double, widen both to double
Else, if either operand is a float, widen both to float
Else, if either operand is a long, widen both to long
Else, widen both to int
So, even if you were adding a byte to a byte, both are widened to int, added, and the result is an int.
The exception to this is if you made c final:
final char c = 34;
In that case, c has a compile-time constant value, so c + 10 is a compile-time constant expression. Because it's a compile-time constant expression, the compiler knows its value, and knows that it fits into the range of char; so it would be allowed:
final char c = 34;
char a = c + 10;

As per the JLS, int is the narrowest type for arithmetic. Narrower values are widened to int, and the result is int.
You would get the same error even if you coded:
char a = c + c; // error

The Java char is a primitive data type. It is used to declare the character-type like char char1='a';
But you can add an int to a char, but the result is an int - you'd have to cast back to char
char a = 'a';
char b = (char)(a+4);
System.out.println(b);// print "e"

Related

Why can't I write ch=ch+1; instead of ch++; though they have same meaning

package practicejava;
public class Query {
public static void main(String[] args) {
char ch = 66;
System.out.println("character= " + ch);
ch++;
System.out.println("character = " + ch);
}
}
Technically ch++; and ch=ch+1; are the same but why do I get an error when I write ch=ch+1; instead of ch++;?
You need to provide a cast in order to do that :
ch = (char) (ch + 1);
This is because the expression ch + 1 is is promoted (upcast) to an int. In order for you to reassign this expression to a char you need to explicitly downcast it.
By ch+1, the char ch will be promoted to int first, just like ((int)ch) + 1, so the result will be an int.
When you try assign an int(32 bit) back to a char(16 bit), it might loss accuracy, you need to do it explictly ch = (char)(ch + 1);
This is called Binary Numeric Promotion:
Binary numeric promotion is performed on the operands of certain
operators:
...
The addition and subtraction operators for numeric types + and - (§15.18.2)
and it will perform
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.
First of all, note that a char is 2 bytes large (16 bit), and an int is 32bit.
1. When typing ch++:
to apply the ++ operator, there is no type cast but the operator simply causes the bit represent of that char to increase by 1 to itself. Refer to JLS11 chapter 15.14.2,page 575:
The type of the postfix increment expression is the type of the variable.
2. When typing ch=ch+1:
ch is firstly casted to int, then it is added by 1(still an int), and the = is actually tring to cast the int which has 32bits into a char which has only 16 bits, note that this may lose accuracy. So without an explicitly cast, the compiler will complain about that, which is the cause of the error.

final characters in Java [duplicate]

This question already has answers here:
Why can not I add two bytes and get an int and I can add two final bytes get a byte?
(3 answers)
Java - char, int conversions
(4 answers)
Closed 8 years ago.
The following segment of code issues a compile-time error.
char c = 'c';
char d = c + 5;
The error on the second line says,
possible loss of precision
required: char
found: int
The error message is based on the NetBeans IDE.
When this character c is declared final like as follows.
final char c = 'c';
char d = c + 5;
The compiler-time error vanishes.
It is unrelated to the case of final strings
What does the final modifier make a difference here?
The reason is that the JLS #5.2 (Assignment conversion) says so:
If the expression is a constant expression (§15.28) of type byte, short, char, or int, a narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.
In your example, char c = 'c'; is not a constant but final char c = 'c'; is.
The rationale is probably that the addition operator + first converts its operands to integers. So the operation could overflow unless everything is constant in which case the compiler can prove that there is no overflow.
When you apply the + operator to integral types
Binary numeric promotion is performed on the operands (§5.6.2).
In this case, the char values are promoted to int values.
Here
char c = 'c';
char d = c + 5;
because c is not a constant expression, the compiler cannot determine if the value of c + 5 which is an int will be able to fit in a char.
In this
final char c = 'c';
char d = c + 5;
where c is a constant expression, the compiler can determine that the value of c, which is 99, added to 5, which is 104 does fit in a char. Because of this guarantee, Java can safely perform a narrowing conversion from int to char.
If instead you had
final char a = Character.MAX_VALUE;
char b = (a + 5);
you would see the similar behavior as your first test case as the value of a + 5 does not fit in a char. The compiler determines that the int value resulting from a + 5 would not fit in a char.

Casting characters in Java

I am learning Java. I found that expressions often have to be cast to a certain type in order to do it right. For example, during arithmetic evaluation, bytes are promoted to integers, so the following expression will throw an error:
byte b = 10;
int i;
i = b*b; //ok, assigning an integer evaluation to an integer variable
b = b*b; // throws error, coz assigning integer evaluation to byte variable
Now, I know that assigning an integer to a character variable is all right: char a; a = 88; is okay. However, if I do this:
char c2 = 'b', c3 = 'c';
c2 = c2 + c3; //throws error
c2 = (char)(c2 + c3); //works fine
Why does it throw an error when not casted? After all, the right hand side is still an integer, so assigning an integer to a character variable should work just fine.
In c2 + c3, both operands are implicitly widened to int, so the result of the addition is also an int.
JLS §15.18.2. Additive Operators (+ and -) for Numeric Types:
Binary numeric promotion is performed on the operands (§5.6.2).
JLS §5.6.2. Binary Numeric Promotion:
When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:
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.
You therefore end up with an int. Assigning it to a char variable requires an explicit cast.
You say:
Since integer value can be assigned to a character variable...
Only constant integer expressions can be assigned to a char variable without a cast.
JLS §5.2. Assignment Conversion:
In addition, if the expression is a constant expression (§15.28) of type byte, short, char, or int:
A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.
This automatic narrowing conversion doesn't apply here. You need an explicit cast.
It does not necessarily work fine to assign an int to a char. Chars are only 16 bit and ints are 32 bit, so the there might be an overflow.
In general Java only allows assignment of primitives values without cast if no overflow can occur as a result of the assignment.
char c2 = 'b', c3 = 'c';
c2 = c2 + c3; //throws error
c2 = (char)(c2 + c3); //works fine
when you doing c2+ c3
ASCII value of these chars are added which returns a int result.
when you are assigning int result to char it gives error.
Assigning an int 88 to a char works, because the compiler can determine the value.
The case c2 = c2 + c3 cannot be handled by the compiler. The value c2 + c3 must be evaluated at run time. Therefore, the compiler cannot determine the actual char value that has to be assigned.
char is 2 bytes and int is 4 bytes. When you write char c = 1; it does not mean that 1 is int, it's just a constant for javac and javac knows that 1 fits into char. But c2 = c2 + c3; is arithmetic operation, javac will interprets it as (int)c2 + (int)c3 and this produces int result. int does not fit into char so javac warns you that there may be lost of precision.
Have a look at thread:
Integer arithmetic in Java with char and integer literal
The reason seems to be that "c2 = c2 + c3;" cannot be checked by the compiler (it is executed in runtime) whereas "char a; a = 88;" is directly done by the compiler.
An example for further clarification:
char c1 = Character.MAX_VALUE;
char c2 = Character.MAX_VALUE;
char c3 = (char) (c1 + c2);
int i3 = c1 + c2;
System.out.printf("After casting to char: %s, the int value: %s%n", (int) c3, i3);
So with casting we actually got a wrong mathematical result.
There is a certain limit as to how much value each basic type can hold in java.Assigning the result of an arithmetic operation can produce an unpredictable result at run-time ,which JVM is unsure if char can hold,therefore the compilation error.

Conversion between character and int in Java

You cannot convert from int to char, so this would be illegal
int i = 88; char c = i;,
However this is allowed char c = 88;.
Isn't a plain number and int literal? How is this allowed?
char is effectively an unsigned 16-bit integer type in Java.
Like other integer types, you can perform an assignment conversion from an integer constant to any integer type so long as it's in the appropriate range. That's why
byte b = 10;
works too.
From the JLS, section 5.2:
In addition, if the expression is a
constant expression (§15.28) of type
byte, short, char or int :
A narrowing primitive conversion may
be used if the type of the variable is
byte, short, or char, and the value of
the constant expression is
representable in the type of the
variable.
A narrowing primitive
conversion followed by a boxing
conversion may be used if the type of
the variable is :
Byte and the value
of the constant expression is
representable in the type byte.
Short
and the value of the constant
expression is representable in the
type short.
Character and the value of
the constant expression is
representable in the type char.
Actually, converting from int to char is legal, it just requires an explicit cast because it can potentially lose data:
int i = 88;
char c = (char) i;
However, with the literal, the compiler knows whether it will fit into a char without losing data and only complains when you use a literal that is too big to fit into a char:
char c = 70000; // compiler error
Its because the literals for integer or smaller than int as byte ,short and char is int. Understand the following in this way.
code:
byte a = 10;//compile fine
byte b= 11;//compile fine
byte c = a+b;//compiler error[says that result of **a+b** is **int**]
the same happens for any mathematical operations as of 'Divide', 'multiply', and other arithmetic operation. so cast the result to get the literal in desired data type
byte c = (byte)(a+b);
So that the same reason why the value int need to have primitive cast to change the value in char.
Hope this make some sense.

Integer arithmetic in Java with char and integer literal

Can someone explain to me why the following code compiles OK in Java?
char c = 'a' + 10;
Why is this not equivalent to the following, which does not compile?
int i = 10;
char c = 'a' + i;
The Java Language Specification (section 3.10.1) states "An integer literal is of type long if it is suffixed with an ASCII letter L or l (ell); otherwise it is of type int (§4.2.1)." Section 4.2.2 refers to "The numerical operators, which result in a value of type int or long." So the result of the addition should, in my understanding, be an int, which cannot be assigned to the char variable c.
However, it compiles fine (at least in Sun JDK 1.6.0 release 17 and in Eclipse Helios).
Rather an artificial example perhaps, but it is used in an introductory Java course I have been teaching, and it now occurs to me that I don't really understand why it works.
It is because the compiler can check that it ('a' + 10) is within the bounds of a char whereas it cannot (in general) check that 'a' + <an integer> is within the bounds.
'a' + 10 is a compile-time constant expression with the value of 'k', which can initialise a variable of type char. This is the same as being able to assign a byte variable with a literal integer in [-128, 127]. A byte in the range of [128, 255] may be more annoying.
char is actually an unsigned 16-bit integer with a range 0-65535. So you can assign any integer literal in that range to a char, e.g., "char c = 96", which results in "c" holding the character "a". You can print out the result using System.out.println(c).
For the constant expression on the right-hand-side of "char c = 'a' + 10", 'a' is promoted to int first because of the Java numeric promotion rules and the integer value is 96. After adding 10 to it, we get a literal integer 106, which can be assigned to a char.
The right-hand-side of "char c = 'a' + i" is not a constant expression and the expression result assignment rule requires an explicit cast from int to char, i.e., "char c = (char) ('a' + i)".
This code should works:
int i = 10;
char x = (char)('a' + i);
The constant is of a different type (I know the spec says that 10 should be an int, but the compiler doesn't see it that way).
In char c = 'a' + 10, 10 is actually considered a constant variable of type char (so it can be added to a). Therefore char c = char + char works.
In int i = 10;
char c = 'a' + i; You are adding a char to an integer (an integer can be much bigger than a char, so it chooses the bigger data type [int] to be the result a.k.a: 'a' + i = int + int). So the result of the addition is an integer, which cannot fit into the char c.
If you explicitly casted i to be a char (e.g.: char c = 'a' + (char)i;) it could work or if you did the opposite (e.g.: int c = (int)'a' + i;) it would work.
According to Java specification as of 2020 for widening and narrowing conversions of integral values in expressions:
"In a numeric arithmetic context ... the promoted type is int,
and any expressions that are not of type int undergo widening
primitive conversion to int"
In assignment context:
"...if the expression is a constant expression of type byte, short,
char, or int:
• A narrowing primitive conversion may be used if the
variable is of type byte, short, or char, and the value of the
constant expression is representable in the type of the variable."
So, in char c = 'a' + 10; the left constant value is a charand the right constant value is int fitting into a char. While there is an assignment and int 10 fits into char, int gets converted to char. And the overall result of addition is char.
And in char c = 'a' + i; (where int i = 10;) the i is not constant, so, notwithstanding the assignment, the char 'a' is promoted to int and the overall result is int. Thus, the assignment is erroneous without an explicit typecast.
Note, that the following original answer is wrong (it cites treatment in numeric choice contexts, like in switch statement):
According to Java specification for widening and narrowing conversions in expressions:
If any expression is of type int and is not a constant expression,
then the promoted type is int, and other expressions that are not of
type int undergo widening primitive conversion to int.
...
if any expression is of type char, and every other expression is
either of type 'char' or a constant expression of type 'int' with a
value that is representable in the type 'char', then the promoted type
is char, and the int expressions undergo narrowing primitive
conversion to char.
So, in char c = 'a' + 10; the left expression is a char and the right constant expression is int fitting into a char. So, the constant gets converted to char. And the overall result is char.
And in char c = 'a' + i; (where int i = 10;) the right expression is not constant, so the the char 'a' is promoted to int and the overall result is int.

Categories