Q:
byteandshortoperands are promoted toint— correct
A more precise wording for this would be:
In most numeric arithmetic expressions, operands of type
byteandshortare promoted toint.
Q: All types are promoted to
double— incorrect
The promotion rules use this order:
double, promote to double.float, promote to float.long, promote to long.int.So types are not always promoted to double.
Examples:
int + int // result: int
int + long // result: long
int + float // result: float
float + double // result: double
Q:
bytecan automatically convert directly tochar— incorrect in the general case
The list of widening conversions from byte includes:
byte → shortbyte → intbyte → longbyte → floatbyte → doubleIt does not include byte → char.
The exact byte-to-char rule is here:
§5.1.4 Widening and Narrowing Primitive Conversion
The JLS explains that byte → char first converts the byte to int, and then narrows the int to char. It is not an ordinary widening conversion.
Therefore, this normally fails:
There is a special exception for certain compile-time constant expressions whose values fit in char, but that does not make general byte variables automatically convertible to char.
An operation involving
floatanddoubleproducesdouble— correct
The rule says:
If any expression has type
double, the promoted type isdouble, and the other numeric expressions are widened todouble.
Therefore:
float first = 1.0F;
double second = 2.0;
double result = first + second;
Before the addition:
float + double
↓
double + double
↓
double
Several operands
byte byteNumber = 1;
int intNumber = 2;
float floatNumber = 3.0F;
double doubleNumber = 4.0;
double result = byteNumber + intNumber + floatNumber + doubleNumber;
The promotion happens step by step:
byte + int → int
int + float → float
float + double → double
Therefore, the final result has type:
The central rule is:
When a numeric operation contains a
doubleoperand, the other numeric operand is widened todouble, and the result of that operation isdouble.
The following code does not compile because Java does not implicitly narrow an int variable to byte:
int a = 135;
byte b = a; // compile-time error
An explicit cast is required:
int a = 135;
byte b = (byte) a;
System.out.println(b); // -121
int to byteAn int uses 32 bits, while a byte uses 8 bits. During the narrowing conversion, only the lowest 8 bits are retained.
The 32-bit representation of 135 is:
00000000 00000000 00000000 10000111
After narrowing to byte, the remaining bits are:
10000111
Java’s byte is an 8-bit signed two’s-complement integer, so this bit pattern must be interpreted as a signed value.
For an unsigned 8-bit integer, the bit weights are:
| Bit position | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|
| Weight | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
Therefore, if 10000111 were unsigned, its value would be:
For an 8-bit signed two’s-complement integer, the highest bit has a negative weight:
| Bit position | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|
| Weight | -128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
The 1 bits in 10000111 are at positions 7, 2, 1, and 0. Therefore:
That is why (byte) 135 is -121.
For an $n$-bit two’s-complement number, the general value formula is:
\[-b_{n-1}2^{n-1} + \sum_{i=0}^{n-2} b_i2^i\]For 8 bits, this becomes:
\[-b_7 \times 128 + b_6 \times 64 + b_5 \times 32 + \cdots + b_0 \times 1\]Each $b_i$ is either 0 or 1.
Another way to interpret 10000111 is:
1, so the number is negative.10000111
↓
01111000
1:01111000 + 1 = 01111001
01111001 to decimal:Therefore, the original value is:
\[-121\]To represent -5 using 8 bits:
5:00000101
11111010
1 to obtain the two’s complement:11111010 + 1 = 11111011
Therefore:
5 = 00000101
-5 = 11111011
The signed-weight method confirms it:
\[-128 + 64 + 32 + 16 + 8 + 2 + 1 = -5\]One’s complement means inverting every bit:
0 → 1
1 → 0
Two’s complement means:
1.Two’s complement is commonly used because:
For example:
\[5 - 3 = 5 + (-3)\] 00000101 // 5
+ 11111101 // -3
-----------
1 00000010
Only 8 bits are retained, so the carry on the left is discarded:
00000010 = 2
byte range is -128 to 127Eight bits provide:
\[2^8 = 256\]possible bit patterns.
In two’s-complement representation:
00000000 to 01111111 represent 0 to 127;10000000 to 11111111 represent -128 to -1.Important boundary values are:
| Binary | Decimal |
|---|---|
01111111 |
127 |
10000000 |
-128 |
10000111 |
-121 |
11111111 |
-1 |
This is why there is no positive 128 in the Java byte type.
An 8-bit value has 256 possible patterns, so narrowing can also be understood using arithmetic modulo 256.
For 135:
Both 135 as an unsigned value and -121 as a signed value correspond to the same 8-bit pattern:
10000111
The bits do not change; only their interpretation changes.
In a pure 8-bit two’s-complement calculation:
01111111 + 00000001 = 10000000
This means:
\[127 + 1 \rightarrow -128\]However, Java normally promotes byte and short operands to int before arithmetic. Therefore:
byte x = 127;
byte y = (byte) (x + 1);
System.out.println(y); // -128
The cast is required because x + 1 has type int.
The central rules are:
During an
int-to-bytenarrowing conversion, Java retains the lowest 8 bits.
In an 8-bit two’s-complement signed number, the highest bit has weight
-128, while the remaining bits have their ordinary positive weights.