This question already has answers here:
Adding char and int
(7 answers)
Closed 9 years ago.
I've got a strange issue with int to char conversion. Here's my code :
char a=100;
System.out.println(a);
System.out.println(a+1);
System.out.println();
System.out.println((char)a+1);
System.out.println((char)101);
System.out.println( (char)a+1==(char)101 );
It gave me this output :
d
101
101
e
true
which is definitly strange : two differents output seems to be the same when compared ! Why is it so ? And how to make a+1 beeing seen as a char ?
Thank you for your answer and sorry if there's some english mistakes, it's not my mothertongue.
In this case
System.out.println((char)a+1);
you are only converting the a to a char (which it is already). The addition makes the whole expression an int, so the overloaded PrintWriter#println(int) gets executed. For it to be seen as a char, do
System.out.println((char) (a+1));
In the JLS
The binary + operator performs addition when applied to two operands
of numeric type, producing the sum of the operands.
The type of an additive expression on numeric operands is the promoted
type of its operands.
and about promotion
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.
When you use this way:
(char)a + 1
It firstly converts a => char, after this you add 1 of type integer.
And result of calculation is upcasted to integer type.
You can omit this tricky place if you will cast all expression together:
(char)(a + 1)
Related
This question already has answers here:
XOR of two short integers
(3 answers)
Why does the Java API use int instead of short or byte?
(7 answers)
Closed 4 years ago.
If I compile this:
1 public class test {
2 public static void main (String args[]) {
3 byte bx = 1;
4 byte by = 2;
5
6 int iz = bx ^ by;
7 byte bz = bx ^ by;
8 byte cbz = (byte)(bx ^ by);
9 }
10 }
then I get this error:
test.java:7: error: incompatible types: possible lossy conversion from int to byte
bz = bx ^ by;
This led me on a brief journey resulting in me deciding ^ always results in an int in a bitwise context. I don't understand why that choice was made.
At first I thought it might have something to do with boxing (or unboxing) but I'm using a primitive type and so I don't think that is part of my confusion.
The only thing I can think of is that byte is promoted to int but I haven't found anything yet that says that's what happens.
Because, in Java, all numeric operators will promote operands to int, long, float, or double, as defined by 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:
If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8).
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.
After the type conversion, if any, value set conversion (§5.1.13) is applied to each operand.
Binary numeric promotion is performed on the operands of certain operators:
The multiplicative operators *, / and % (§15.17)
The addition and subtraction operators for numeric types + and - (§15.18.2)
The numerical comparison operators <, <=, >, and >= (§15.20.1)
The numerical equality operators == and != (§15.21.1)
The integer bitwise operators &, ^, and | (§15.22.1)
In certain cases, the conditional operator ? : (§15.25)
If you declare variables of type byte or short and attempt to perform arithmetic operations on these, you receive the error "Type mismatch: cannot convert int to short" (or correspondingly "Type mismatch: cannot convert int to byte").
byte a = 23;
byte b = 34;
byte c = a + b;
In this example, the compile error is on the third line.
Although the arithmetic operators are defined to operate on any numeric type, according the Java language specification (5.6.2 Binary Numeric Promotion), operands of type byte and short are automatically promoted to int before being handed to the operators.
To perform arithmetic operations on variables of type byte or short, you must enclose the expression in parentheses (inside of which operations will be carried out as type int), and then cast the result back to the desired type.
byte a = 23;
byte b = 34;
byte c = (byte) (a + b);
Here's a follow-on question to the real Java gurus: why? The types byte and short are perfectly fine numeric types. Why does Java not allow direct arithmetic operations on these types? (The answer is not "loss of precision", as there is no apparent reason to convert to int in the first place.)
Update: jrudolph suggests that this behavior is based on the operations available in the JVM, specifically, that only full- and double-word operators are implemented. Hence, to operator on bytes and shorts, they must be converted to int.
The answer to your follow-up question is here:
operands of type byte and short are automatically promoted to int before being handed to the operators
So, in your example, a and b are both converted to an int before being handed to the + operator. The result of adding two ints together is also an int. Trying to then assign that int to a byte value causes the error because there is a potential loss of precision. By explicitly casting the result you are telling the compiler "I know what I am doing".
I think, the matter is, that the JVM supports only two types of stack values: word sized and double word sized.
Then they probably decided that they would need only one operation that works on word sized integers on the stack. So there's only iadd, imul and so on at bytecode level (and no operators for bytes and shorts).
So you get an int value as the result of these operations which Java can't safely convert back to the smaller byte and short data types. So they force you to cast to narrow the value back down to byte/short.
But in the end you are right: This behaviour is not consistent to the behaviour of ints, for example. You can without problem add two ints and get no error if the result overflows.
The Java language always promotes arguments of arithmetic operators to int, long, float or double. So take the expression:
a + b
where a and b are of type byte. This is shorthand for:
(int)a + (int)b
This expression is of type int. It clearly makes sense to give an error when assigning an int value to a byte variable.
Why would the language be defined in this way? Suppose a was 60 and b was 70, then a+b is -126 - integer overflow. As part of a more complicated expression that was expected to result in an int, this may become a difficult bug. Restrict use of byte and short to array storage, constants for file formats/network protocols and puzzlers.
There is an interesting recording from JavaPolis 2007. James Gosling is giving an example about how complicated unsigned arithmetic is (and why it isn't in Java). Josh Bloch points out that his example gives the wrong example under normal signed arithmetic too. For understandable arithmetic, we need arbitrary precision.
In Java Language Specification (5.6.2 Binary Numeric Promotion):
1 If any expression is of type double, then the promoted type is double, and other expressions that are not of type double undergo widening primitive conversion to double.
2 Otherwise, if any expression is of type float, then the promoted type is float, and other expressions that are not of type float undergo widening primitive conversion to float.
3 Otherwise, if any expression is of type long, then the promoted type is long, and other expressions that are not of type long undergo widening primitive conversion to long.
4 Otherwise, none of the expressions are of type double, float, or long. In this case, the promoted type is int, and any expressions that are not of type int undergo widening primitive conversion to int.
Your code belongs to case 4. variables a and b are both converted to an int before being handed to the + operator. The result of + operation is also of type int not byte
This question already has answers here:
=+ Operator in Java
(4 answers)
Closed 8 years ago.
Came across someone mistakenly using =+ instead of += in their code and it didn't show up as a compile error.
Is this because
int a =+ 2;
is the same as
int a = 0 + 2;
?
There's no compilation error because + is a valid (albeit fairly useless) unary operator in the same way that - is:
int x = +1;
int y = -1;
The relevant section in the Java Language Specification is Unary Plus Operator + (§15.15.3 ). It specifies that invoking the unary + operation results in Unary Numeric Promotion (§5.6.1) of the operand. This means that:
If the operand is of compile-time type Byte, Short, Character, or Integer, it is subjected to unboxing conversion
(§5.1.8).
The result is then promoted to a value of type int by a widening
primitive conversion
(§5.1.2)
or an identity conversion
(§5.1.1).
Otherwise, if the operand is of compile-time type Long, Float, or Double, it is subjected to unboxing conversion
(§5.1.8).
Otherwise, if the operand is of compile-time type byte, short, or char, it is promoted to a value of type int by a widening
primitive conversion
(§5.1.2).
Otherwise, a unary numeric operand remains as is and is not converted.
In any case, value set conversion
(§5.1.13)
is then applied.
In short, this means that
numeric primitive wrapper types are unboxed, and;
integer types smaller than int are widened to int.
There may be a bug lurking here. The writer may have intended to write a += 2;
In the original version of C, a += 2; and a =+ 2; were synonyms. If you meant a = +2;, you had to be careful to leave a space between the = and the +. Same with all the other operators. a=*p; multiplied a by p. a = *p; de-referenced the pointer p and assigned the result to a.
Then they came to their senses, and started giving warnings for =op where op= was probably intended, and now no longer accept =op at all.
But old habits die hard. An old-school C programmer might might still absent-mindedly use old-school syntax, even when writing in a language other than C.
On the other hand, the = in int x =+ 2; is an initialization, not an assignment, and it would be bizarre for a programmer to think in terms of incrementing a variable that is only just now being given its initial value.
This question already has answers here:
Strange java behaviour with conditional operator. Is it a bug?
(2 answers)
Closed 9 years ago.
public static void main(String[] args) {
Object o=true?new Integer(1):new Double(1.0);
System.out.println(o);
}
I am getting 1.0 as output, first upon above else statement is unreachable but how it auto type casted.
The JLS states that
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.
that is in an expression
true? Integer(1) : Double(1.0)
since one of the operand here is a Double the return type is also double
http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6
The keyword is "Numeric Promotion":
Numeric promotions are used to convert the operands of a numeric
operator to a common type so that an operation can be performed. The
two kinds of numeric promotion are unary numeric promotion (§5.6.1)
and binary numeric promotion (§5.6.2).
sᴜʀᴇsʜ ᴀᴛᴛᴀ already gave you a link explaining your concrete example.
If you declare variables of type byte or short and attempt to perform arithmetic operations on these, you receive the error "Type mismatch: cannot convert int to short" (or correspondingly "Type mismatch: cannot convert int to byte").
byte a = 23;
byte b = 34;
byte c = a + b;
In this example, the compile error is on the third line.
Although the arithmetic operators are defined to operate on any numeric type, according the Java language specification (5.6.2 Binary Numeric Promotion), operands of type byte and short are automatically promoted to int before being handed to the operators.
To perform arithmetic operations on variables of type byte or short, you must enclose the expression in parentheses (inside of which operations will be carried out as type int), and then cast the result back to the desired type.
byte a = 23;
byte b = 34;
byte c = (byte) (a + b);
Here's a follow-on question to the real Java gurus: why? The types byte and short are perfectly fine numeric types. Why does Java not allow direct arithmetic operations on these types? (The answer is not "loss of precision", as there is no apparent reason to convert to int in the first place.)
Update: jrudolph suggests that this behavior is based on the operations available in the JVM, specifically, that only full- and double-word operators are implemented. Hence, to operator on bytes and shorts, they must be converted to int.
The answer to your follow-up question is here:
operands of type byte and short are automatically promoted to int before being handed to the operators
So, in your example, a and b are both converted to an int before being handed to the + operator. The result of adding two ints together is also an int. Trying to then assign that int to a byte value causes the error because there is a potential loss of precision. By explicitly casting the result you are telling the compiler "I know what I am doing".
I think, the matter is, that the JVM supports only two types of stack values: word sized and double word sized.
Then they probably decided that they would need only one operation that works on word sized integers on the stack. So there's only iadd, imul and so on at bytecode level (and no operators for bytes and shorts).
So you get an int value as the result of these operations which Java can't safely convert back to the smaller byte and short data types. So they force you to cast to narrow the value back down to byte/short.
But in the end you are right: This behaviour is not consistent to the behaviour of ints, for example. You can without problem add two ints and get no error if the result overflows.
The Java language always promotes arguments of arithmetic operators to int, long, float or double. So take the expression:
a + b
where a and b are of type byte. This is shorthand for:
(int)a + (int)b
This expression is of type int. It clearly makes sense to give an error when assigning an int value to a byte variable.
Why would the language be defined in this way? Suppose a was 60 and b was 70, then a+b is -126 - integer overflow. As part of a more complicated expression that was expected to result in an int, this may become a difficult bug. Restrict use of byte and short to array storage, constants for file formats/network protocols and puzzlers.
There is an interesting recording from JavaPolis 2007. James Gosling is giving an example about how complicated unsigned arithmetic is (and why it isn't in Java). Josh Bloch points out that his example gives the wrong example under normal signed arithmetic too. For understandable arithmetic, we need arbitrary precision.
In Java Language Specification (5.6.2 Binary Numeric Promotion):
1 If any expression is of type double, then the promoted type is double, and other expressions that are not of type double undergo widening primitive conversion to double.
2 Otherwise, if any expression is of type float, then the promoted type is float, and other expressions that are not of type float undergo widening primitive conversion to float.
3 Otherwise, if any expression is of type long, then the promoted type is long, and other expressions that are not of type long undergo widening primitive conversion to long.
4 Otherwise, none of the expressions are of type double, float, or long. In this case, the promoted type is int, and any expressions that are not of type int undergo widening primitive conversion to int.
Your code belongs to case 4. variables a and b are both converted to an int before being handed to the + operator. The result of + operation is also of type int not byte