The
Java IO stream library does seem to satisfy the basic requirements: you can
perform reading and writing with the console, a file, a block of memory, or
even across the Internet (as you will see in Chapter 15). It’s possible
(by inheriting from
InputStream
and
OutputStream)
to create new types of input and output objects. And you can even add a simple
extensibility to the kinds of objects a stream will accept by redefining the
toString( )
method that’s automatically called when you pass an object to a method
that’s expecting a
String
(Java’s limited “automatic type conversion”).
There
are questions left unanswered by the documentation and design of the IO stream
library. For example, it would have been nice if you could say that you want an
exception thrown if you try to overwrite a file when opening it for output
– some programming systems allow you to specify that you want to open an
output file, but only if it doesn’t already exist. In Java, it appears
that you are supposed to use a
File
object to determine whether a file exists, because if you open it as an
FileOutputStream
or
FileWriter
it
will always get overwritten. By representing both files and directory paths, the
File
class also suggests poor design by violating the maxim “Don’t try
to do too much in a single class.”
The
IO stream library brings up mixed feelings. It does much of the job and
it’s portable. But if you don’t already understand the decorator
pattern, the design is non-intuitive, so there’s extra overhead in
learning and teaching it. It’s also incomplete: there’s no support
for the kind of output formatting that almost every other language’s IO
package supports. (This was not remedied in Java 1.1, which missed the
opportunity to change the library design completely, and instead added even
more special cases and complexity.)
The Java 1.1 changes to the IO library haven’t been replacements, but
rather additions, and it seems that the library designers couldn’t quite
get straight which features are deprecated and which are preferred, resulting
in annoying deprecation messages that show up the contradictions in the library
design.
However,
once you
do
understand the decorator pattern and begin using the library in situations that
require its flexibility, you can begin to benefit from this design, at which
point its cost in extra lines of code may not bother you as much.