Java shifts right to output negative values

Java shifts right to output negative values … here is a solution to the problem.

Java shifts right to output negative values

I’m really confused, I’d better show my code first, that’s what I get.

void dumpInt(int x) throws IOException {
    if ( true ) {
        8388638
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        writer.writeByte(x&0xff);
        writer.writeByte((x>>8)&0xff);
        writer.writeByte((x >> 16) & 0xfff);
        writer.writeByte((x>>24)&0xff);
        outputStream.write(x & 0xff);
        outputStream.write((x >> 8) & 0xff);
        outputStream.write((x >> 16) & 0xff);
        outputStream.write((x >> 24) & 0xff);
        System.out.println((x >> 16) & 0xff);
        if(x == 8388638){
            String xz = "";
            byte[]array = outputStream.toByteArray();
            System.out.println(array[2]+" | " + (char)array[2]);
        }
    } else {
        writer.writeInt(x);
    }
}

This works great, but when I do dumpInt(8388638) I run into something weird.
writer.writeByte((x >> 16) & 0xfff) writes -128 to writer
I don’t know why this is happening.

The same thing happens with outputStream.write(x >> 16) & 0xff); But when I run System.out.println((x >> 16) & 0xff ); Output 128 (positive).

Does anyone know why this is and how I can correct it?
(Sorry, I have a bit of experience with Java, but I’m not the best anyway, so if this is a very simple fix my bug)

Solution

Bytes in Java are signed in the range -128~127. You seem to be more familiar with another decimal representation of bytes – unsigned bytes, ranging from 0 to 255. However, it does not exist as a separate data type in Java.

The following are the corresponding values for the two representations:

  signed    -128 -127 -126 ... -1   0   1   ...   126 127 128
unsigned    128  129  130  ... 255  0   1   ...   126 127 128

Note: These are not really different binary representations. They have the same binary representation. This depends on whether you interpret the MSB as a sign bit.

You can convert

from a signed version to an unsigned version by Byte.toUnsignedInt, and you can convert to a signed version by converting to byte.

For some reasons why you must ask the API designer, OutputStream.write accepts unsigned bytes (as well as signed bytes). If byte has a range of -128 to 127, how can Java do that? It accepts ints instead of byte!

write (

writeByte is also called) converts int 128 to (signed) byte -128 and writes it to the stream. When you get the bytes written later, you will get the converted signed byte. But in reality, in terms of bits, 128 and -128 are the same 1000 0000. It’s just that Java insists on interpreting the first 1 as a sign bit.

As I said earlier, you can convert -128 to 128‘: if you prefer other representations

Byte.toUnsignedInt(-128) // 128

Note that the result must be int because the result is outside the scope of byte.

Related Problems and Solutions