# Arithmetic Promotion. What's the deal here?

Tophe Wamp
Greenhorn
Posts: 5
byte b = 5;
b = ++b; // does compile
b = b++; // does compile
b = +b; // does NOT compile
b = -b; // does NOT compile
okay. I have one book (Complete Java 2 Certification Study Guide) that says that bytes, shorts, and chars are converted to ints for unary operators EXCEPT for ++ and -- (p111). That I can understand. And that is what is happening here. Now the companion book for that (Java 2 Exam Notes) says, "For unary arithmetic...is promoted to an int...the result is of type int" ignoring the ++ and -- exception. (I found this book to have NUMEROUS typos and inconsistencies.) But I agree with the big book.
Now figure this one out:
byte b = 5;
b += 1; // constant integral
b += b; // another byte
b += 1048576; // int constant
int i = 1048576; // clearly an int
b += i;
long l = 2147483647 + 10; // clearly a long
b += l;
double d = 12.3; // clearly a double
b += d;
All of this compiles. So why is there "no" promotion going on during compilation?
As an added bonus:
long l = (long) 4294967296;
produces this compiler error:
Integer literal out of range.
Decimal int literals must be in the range.
So I'm assuming long literals do not exist.
tophe.

Stevie Kaligis
Ranch Hand
Posts: 400

Q#1 :
byte b = 5;
you assign integer literal (5) directly to b, so the constant value will be type byte.
b = +b or b = -b //Does NOT compile
you are NOT assign integer literal (5) directly to b, but you are using variable "b" and you add a unary arithmetic (+/-), so because this is a unary, it will be promote to "int", that's why it won't compile, you need to do an explicit cast : b = (byte)-b .
Q#2 :
Remember this rule :
Given : the variable of type is 'T', the value is 'expr', and the binary operator 'op',
the expression : var op= expr,
is equivalent to : var = (T)((var) op (expr)).
byte b = 5;
b += 1; // b = (byte)((b) + (1))
b += b; // straightforward
b += 1048576; // b = (byte)((b) + (1048576))
int i = 1048576; // clearly an int
b += i; // b = (byte)((b) + (i)) note : b+i return int.
long l = 2147483647 + 10; // clearly a long
b += l; // b = (byte)((b) + (l)) note : b+l return long.
double d = 12.3; // clearly a double
b += d; // b = (byte)((b) + (d)) note : b+d return double.
Q#3 :
long l = (long) 4294967296;
even the code is :
long l = 4294967296;
first compiler will evaluate the int number (4294967296)before assign it to l.
since the int number is to large, it won't compile.
if you want to assign number outside of the range, the integer constant must followed with "L" for "long", and "D" for double.
so the code will be :
long l = 4294967296L;
bonus :
List of Literals :
1. Reference Literal : constant value is "null",
2. Primitive Literals :
a. boolean : constant value "true" & "false"
b. character : single quotes 'x'
c. integer : constant value are asume "int"
this include (byte, short, int, long, Dec, Octal, Hex).
d. floating point : constant value are assume "double"
this include (double)
3. String Literals : double quotes "..xxx.."
4. Class Literals : every type is an associated class object :
for example : String.class, boolean.class

hope this help.
stevie

Tophe Wamp
Greenhorn
Posts: 5
Q1:
"byte b = 5; you assign integer literal (5) directly to b, so the constant value will be type byte."
That's only half true. byte b = 128; will not compile. So the compiler knows if the int value will fit into the smaller type.
And I want to point out again that ++/-- are an exception to the unary promotion rule.
Q2:
"var op= expr,
is equivalent to : var = (T)((var) op (expr))."
That's what I needed. That's the best way (actually the only way) I've seen this explained. This needs to be in my book.
Q3:
duh, I should have known that.
Here's some more strange behavior I found:
int i = (char) 1; // will compile
char c = (int) 65; // will compile
char c2 = (int) 65536; //won't compile
char c3 = (byte) 65; //won't compile
The behavior of the first three lines I expect. But the byte should fit into the char, so why not compile (and run)? It's b/c promotion isn't exactly linear through the primitive types. bytes and shorts and chars can be promoted to ints. But bytes and shorts can't be promoted to chars. (Complete Java 2 Study Guide p108).

Stevie Kaligis
Ranch Hand
Posts: 400
int i = (char) 1; // will compile
char c = (int) 65; // will compile
char c2 = (int) 65536; //won't compile
char c3 = (byte) 65; //won't compile
according to your code given, i think c3 will compile without any problem !!!
note :
1. implicit conversion :
conversion from smaller type to larger type : widening
2. explicit conversion :
converison from larger type to smaller type : narrowing
char & short are special :
char x = 65;
short y = x; //WON'T COMPILE
or
short x = 65;
char y = x; //WON'T COMPILE
There are no widening(implicit conversion) from char to short and VICE VERSA, you must use narrowing(explicit conversion).
The reason is because they both 16 bit, same range, BUT diferent LARGER ranges of values (char range of values is 0 to 65535(largest), short range of values is -32768 to 32768(largest)).
hope this help
stevie

Stevie Kaligis
Ranch Hand
Posts: 400
I'm sorry I missed type,
the largest range value for short is : 32767.
hope it's clear.
stevie