Maybe someone can help me understand because I feel I\'m missing something that will likely have an effect on how my program runs.
I\'m using a ByteArrayOutputStream
That's mostly because the Java Virtual Machine model's stack hates byte
, but loves int
. The stack uses 32-bit slots , which matches the size of an int
.
You will notice however that java *does* like byte[]
references. But that's because the content of arrays is stored in the heap (not the stack). And whenever a specific byte
is addressed and moved to the stack (the bipush
or sipush
opcodes) then they are immediately converted to integers.
But sometimes java actually uses 257(!) values. When an InputStream#read()
returns 256 values, but when it has no content it will return a -1
value. Alternatively, it would have been possible to throw an EOFException
(like some other methods do) but exceptions are slow in java.
Even though you don't need the -1
value for the OutputStream#write
it's coherent, and it reduces casting. But yes, it's missleading too.
In order to facilitate unsigned bytes above 0x7F
this takes place. The int will be silently narrowed to be written. In fact, the code does that with a (byte)
cast.
As Ingo states:
A possible reason could be that the byte to write will most often be the result of some operation that automatically converts its operands to int[, like] some bit operations. Hence, the code would be littered with casts to byte, that add nothing to understanding.
ByteArrayOutputStream
is just overriding the abstract method declared in OutputStream
. So the real question is why OutputStream.write(int) is declared that way, when its stated goal is to write a single byte to the stream. The implementation of the stream is irrelevant here.
Your intuition is correct - it's a broken bit of design, in my view. And yes, it will lose data, as is explicitly called out in the docs:
The byte to be written is the eight low-order bits of the argument b. The 24 high-order bits of b are ignored.
It would have been much more sensible (in my view) for this to be write(byte)
. The only downside is that you couldn't then call it with literal values without casting:
// Write a single byte 0. Works with current code, wouldn't work if the parameter
// were byte.
stream.write(0);
That looks okay, but isn't - because the type of the literal 0 is int
, which isn't implicitly convertible to byte
. You'd have to use:
// Ugly, but would have been okay with write(byte).
stream.write((byte) 0);
For me that's not a good enough reason to design the API the way it is, but that's what we've got - and have had since Java 1.0. It can't be fixed now without it being a breaking change all over the place, unfortunately.