Java doesn’t have unsigned types. In order to convert C++ unsigned values to Java you may need to use larger types. Authors of the language explain it as the Java should be a simple language and be easy to understand for all developers.
Problems occur when you need to convert to or from Java numeric types. Let us look at C++ vs Java types:
C++ Type *) | Java Type |
---|---|
8-bit unsigned byte | (signed) byte |
16-bit unsigned short | (signed) short |
32-bit unsigned int | (signed) int |
32-bit/64-bit unsigned long | (signed) long |
32-bit float | float |
64-bit double | double |
*) With C++, the types aren’t as rigidly defined in Java. The only requirement is that a char is not larger than a short, a short is not larger than an int, and an int is not larger than a long, where a short may not be smaller than 16-bits, an int may not be smaller than 32-bits and a long long at least 64-bits. It’s perfectly valid for a C++ system where are types are 64-bits.
Most of the time you don’t need to use larger numeric types.
Example of the simplest case of conversion between C++ unsigned int coded bytes to Java Integer:
1. Read 4 bytes into an Integer
int length = ByteBuffer.wrap(bytes, 0, 4).getInt();
2. Convert Integer value to 4 bytes:
final byte[] bytes = intToByte(length); private static byte[] intToByte(int value) { return ByteBuffer.allocate(4).putInt(value).array(); }
In case when you need to account for all possible values of unsigned values in Java, you should convert from unsigned type to a larger numeric type and back.
Example of converting a C++ unsigned int to Java long: C++ layer converts unsigned int values to 4 bytes and sends it to Java layer. Java layer converts bytes to long type, analyses the data and sends the response, converting long back to 4 bytes data.
1. Read the 4 bytes and store them as long:
long length= ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt() & 0xFFFFFFFFL;
2. Convert Java long value back to 4 bytes data array:
final byte[] bytes = longToByte(length); public static byte[] longToByte(long value) { byte [] data = new byte[4]; data[3] = (byte) value; data[2] = (byte) (value >>> 8); data[1] = (byte) (value >>> 16); data[0] = (byte) (value >>> 32); return data; }
Note, you can’t use a ByteBuffer here to convert Java long to 4 bytes. Java long is stored as 8 bytes and ByteBuffer will return an 8-bytes array. You need to use bitwise operations in order to set values back to 4 bytes array.
This post doesn’t take into account there are at least three types of endian-ness. Little endian as most Intel CPUs, big endian and then there is middle endian. Implementing those are left as an excercise for the reader.