Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does ByteArrayOutputStream use int?

Tags:

java

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. Unless I've missed something huge, the point of this class is to create a byte[] array for some other use.

However, the "plain" write function on BAOS takes an int not a byte (ByteArrayOutputStream.write).

According to this(Primitive Data Types) page, in Java, an int is a 32-bit data type and a byte is an 8-bit data type.

If I write this code...

int i = 32;
byte b = i;

I get a warning about possible lossy conversions requiring a change to this...

int i = 32;
byte b = (byte)i;

I'm really confused about write(int)...

like image 945
Ari Black Avatar asked Jan 29 '14 18:01

Ari Black


People also ask

Is it necessary to close ByteArrayOutputStream?

In summary: It does no harm to flush() or close() a bare ByteArrayOutputStream . It is just unnecessary.

What is ByteArrayOutputStream in java?

ByteArrayOutputStream class creates an Output Stream for writing data into byte array. The size of buffer grows automatically as data is written to it. There is no affect of closing the byteArrayOutputStream on the working of it's methods. They can be called even after closing the class.

Is ByteArrayOutputStream thread safe?

Yes it is thread safe, or rather all its methods are synchronized, and ProcessBuilder.


2 Answers

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.

like image 99
nanofarad Avatar answered Oct 09 '22 06:10

nanofarad


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.

like image 5
Jon Skeet Avatar answered Oct 09 '22 07:10

Jon Skeet