views:

96

answers:

3

The block quotes are from the Java Docs -

A FilterInputStream contains some other input stream, which it uses as its basic source of data, possibly transforming the data along the way or providing additional functionality.

A DataInputStream lets an application read primitive Java data types from an underlying input stream in a machine-independent way.

The DataInputStream therefore extends FilterInputStream

An ObjectInputStream deserializes primitive data and objects previously written using an ObjectOutputStream.

However, for some reason the ObjectInputStream does NOT extend FilterInputStream even though it is also reading objects (this time and not primitive types) from the underlying input stream. Here is the branching of the concerned classes.

alt text

Is there is a design reasoning for the same?

+1  A: 

I guess ObjectInputStream had to override every method of FilterInputStream.

When you do this there is not really a point of maintaining that relationship.

What's important: ObjectInputStream IS an InputStream ( you still can write primitive data to it in addition to other methods ) and that relationship is there.

Alexander Pogrebnyak
FilterInputStream does not add any additional method apart from InputStream; it just implements all methods provided in the InputStream
Vaibhav Bajpai
@Vaibhav Bajpai: If you look at Sun's implementation, you will see that it wraps not the InputStream that has been passed in, but a private inner class called BlockDataInputStream. Once you have no use for FilterInputStream.in memver, you really don't need it anymore.
Alexander Pogrebnyak
@Vaibhav Bajpai: I found that in a few instances when I had to implement a delegated input/output stream I was always better by bypassing FilterInputStream and especially it's evil cousen FilterOutputStream. In case of FilterOutputStream it implements it's `write( byte[] )` method in terms of a loop that calls `write( int )` the size of the buffer. I've spent a lovely 2 days trying to figure out why the heck performance was so bad after switching regular stream with my version. That's one of the worst cases when you have to know the implementation of the base class.
Alexander Pogrebnyak
+1  A: 

There is distinction between:

  • Logical inheritance (shares interface)
  • 'Code' inheritance when you share the code between classes

Logically LinkedList is not AbstractList as it is not abstract. However from the code point of view it is benefitial to share some implementation of List methods as they can be implement in terms of others, usually with the same efficiency (for example isEmpty can be implemented as size() == 0).

Some platforms, such as GObject (or to some extend Haskell - although it is not OO language and many things are totally different) alows default implementation of methods in interface which is defining it.

However it is not the case with Java which uses Abstract* classes to reuse the code. Filter*Stream is not so much defining that the output is sent somewhere (as the whole point of the Java I/O is that the produer/reciver does not care) but it is used to reuse common code.

Maciej Piechotka
A: 

Sensible question. Thinking of it, I believe that Object*Stream could have been designed to extend Filter*Stream (the same applies to Output or Input). Why it wasn't done so? Perhaps because:

  1. It gives no real benefit. As explained by Maciej, the point of Filter*Stream, apart from some unimportant organization of classes, is to provide some common default (and rather trivial) implementation of those classes that have that pattern (read/write from some underlying stream, eventually transforming the stream), to be extended by other classes (from Java API or user). But Filter*Stream is not about interfaces : you'll almost never find or implement some method that requires a Filter*Stream as argument, for example. Hence, the decision of making a class inherit *Stream or Filter*Stream, when there is the alternative, is mostly an implementation decision; the users of the class will basically not care.

  2. The designers of ObjectOutputStream decided to give extra flexibility to those willing to extend the class, totally reimplementing it, by giving an extra empty constructor (with no underlying OuputStream). This feature (rather rare, I think) puts the class (conceptually and implementation wise) a litte far apart the Filter*Stream class. Again, this does not seem conclusive.

leonbloy