June 2008
Sommaire |
1 Generality
In Java the various integers (byte, short, int, long) are :
- all signed using the two's complement
- stored in the big-endian order
The binary operators for this integers are :
- the bitwise NOT (~)
- the bits shifts (<<, >>, >>>)
- the logical bitwise between two integers (&, | , ^)
For more details : Integers, Little and Big Endian, Bitwise Operations
2 Distinctive feature
Java implicitly converts the shorts and the bytes to int when he does a binary operation. The compilation of this class shows it easlily :
1 class DistinctiveFeature {
2 public static void main(String args[]) {
3 byte byte1= 1;
4 byte byte2 = 2;
5 short short = 1;
6 byte2 = byte1 | byte2;
7 short = ~short;
8 }
9 }
the result of compilation is :
javac DistinctiveFeature.java
DistinctiveFeature.java:7: possible loss of precision
found : int
required: byte
byte2 = byte1 | byte2;
^
DistinctiveFeature.java:8: possible loss of precision
found : int
required: short
short = ~short;
^
2 errors
In fact the lines 6 and 7 are equivalent to :
6 byte2 = (int)byte1 | (int)byte2; 7 short = ~(int)short;
We can cast the result before the assignement to solve this difficulty :
6 byte2 = (byte)(byte1 | byte2); 7 short = (short)(~short);
in this case there are no problems, but we are going to see that this solution can give sometimes wrong results.
3 Difficulty
In some cases, using an int instead of a byte or a short generates an error, here are 2 examples :
- left shift don't discard the left bit :
class DistinctiveFeature {
public static void main(String args[]) {
byte byte1= 64;
short short = 512;
short = (short)(short | (byte1 << 2));
System.out.println("Expected : "+512+" / Result : " +short);
}
}
Expected : 512 / Result : 768
Explication : 768 = 512 + 256 the bit 64 is not discared by left shift because we work on an int.
- binary operation to make a short from 2 bytes read in a stream :
class DistinctiveFeature {
public static void main(String args[]) {
byte byte1= -1; // 255 or 0xFF
byte byte2 = 1;
short short = 0;
short = (short)(byte1 | (byte2 << 8));
System.out.println("Expected : "+(256+255)+" / Result : " +short);
}
}
Expected : 511 / Result : -1
Explication : the byte1 0xFF was converted in int 0xFFFFFFFF, the OR with the shiffed byte2 0x0100 give 0xFFFFFFFF instead of 0x01FF expected.
4 Solution
We must remove the useless bits of the int created by the implicit convertion. Therefore we apply an AND with 0xFF for the bytes or 0xFFFF for the shorts, so the int is correct.
Which give for the 2 previous examples :
class DistinctiveFeature {
public static void main(String args[]) {
byte byte1= 64;
short short = 512;
short = (short)(short | ((byte1 << 2) & 0xFF));
System.out.println("Expected : "+512+" / Result : " +short);
}
}
Expected : 512 / Result : 512
class DistinctiveFeature {
public static void main(String args[]) {
byte byte1= -1; // 255 or 0xFF
byte byte2 = 1;
short short = 0;
short = (short)((byte1 & 0xFF) | ((byte2 << 8));
System.out.println("Expected : "+(256+255)+" / Result : " +short);
}
}
Expected : 511 / Result : 511