0

I understand that this can be done using wrapper pattern, but i am having a hard time understanding, how does the following code work.

ByteArrayOutputStream bytearray = new ByteArrayOutputStream();
DataOutputStream os = new DataOutputStream(bytearray);

passing ByteArrayOutputStream reference into the constructor of DataOutputStream means that the DataOutputStream gets converted to ByteArrayOutputStream, but how?

After this, os.writeUTF("String"); How does DataOutputStream convert to ByteArrayOutputStream.

What is happening behind the scenes? Can somebody please explain the details.

Kazekage Gaara
  • 14,972
  • 14
  • 61
  • 108
ARAZA
  • 225
  • 1
  • 3
  • 10

2 Answers2

5

The DataOutputStream only requires any implementation of an OutputStream in its constructor. It doesn't care how it's implemented only that it satisfies the interface. A ByteArrayOutputStream provides an output stream backed by a byte array. Similarly, you could use a FileOutputStream to get a stream backed by a file on disk. From the DataOutputStream's perspective, they are both streams that used with an interface. OutputStream is a really simple interface, and just defines some methods that write byte arrays to some kind of storage device.

There's no magic going on under the scenes, it just uses an OutputStream and doesn't care how it's implemented.

Jeff Foster
  • 43,770
  • 11
  • 86
  • 103
  • Thank you for your answer, i understand both implement the OutputStream, but my question is how does DataOutputStream.write("something") gets converted to ByteArrayOutputStream. I was going through the sourcecode, and when DataOutputStream() constructor is called, it takes an Outputstream reference which is what we are doing and when DataOutputStream.write() is called, in the method we see that the reference which was passed in the constructor (in our case bytearray), it actually calls the write method of this reference, bytearray.write(), i think this is where it gets converted to ByteArray. – ARAZA Dec 24 '12 at 18:46
0

Actually this can be called Decorator pattern. DataOutputStream takes any existing OutputStream (ByteArrayOutputStream in our case) and stores a reference to it in

protected OutputStream out;

(Actually it is in java.io.FilterOutputStream that DataOutputStream extends).

Now lets see how DataOutputStream.writeInt works (writeUTF is too heavy)

public final void writeInt(int v) throws IOException {
    out.write((v >>> 24) & 0xFF);
    out.write((v >>> 16) & 0xFF);
    out.write((v >>>  8) & 0xFF);
    out.write((v >>>  0) & 0xFF);
...

it simply takes an int arg and writes its 4 bytes, byte by byte, using the regular OutputStream.write(byte). In our case these bytes will be written into ByteArrayOutputStream internal byte array. If can change ByteArryOutputStream to FileOuputStream and the data will be written to a file, DataOutuputStream does not need to know about the actual implementation.

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275