4

It make sense to see close() as non-core functionality of stream objects. This is the reason this method is placed in interface Closeable. One evidence is that class ByteArrayInputStream does not require the close() operation.

public abstract class InputStream implements Closeable {}

public abstract class OutputStream implements Closeable, Flushable {}

Based on the above definitions my observation is that interface Closeable should not be implemented by abstract class InputStream/OutputStream; it has to be left to concrete sub-classes (like class FileInputStream) to implement it.

enter image description here

Do you think my understanding is correct?

  • it is part of it, the closeable interface is a retro fit – ratchet freak Dec 20 '14 at 14:40
  • Do we need to introduce interface Closeable to retrofit? – overexchange Dec 20 '14 at 14:46
  • Does class ByteArrayInputStream require close() operation? I guess close() operation is mainly required when you communicate via file descriptors of the process. – overexchange Dec 20 '14 at 14:55
  • @ratchetfreak Only correction for the current impl could be, interface Closeable should have been implemented by concrete sub classes of abstract class InputStream instead of InputStream itself implementing it. – overexchange Dec 20 '14 at 15:04
5

Just my two cents. The goal of this answer is to give some thoughts and attract more answers, not trying to sound like definitive or even informative.


Why are streams abstract base classes instead of interfaces?

  • It is possible to define a strictly minimal interface.
    • Typically this consists of: read, write, seek, tell (returns current file position), get length, truncate (reduce file size), close.
  • However, to make the stream implementation convenient to use, a lot of helper methods on the class would be needed.
    • Without these helper methods, it would make the programming language impractical, because it would then be too troublesome to use streams as a fundamental feature of the standard library.
    • These helper methods make use of the minimal interface.
    • Typically, default (standard) implementations can be provided for these helper methods, that would completely satisfy the needs most of the time.
    • Therefore, abstract base classes are used to provide these default helper method implementations to improve the usability of the standard library.

Is the close() method fundamental to the operation of streams?

Contrary to your point of view, I would argue that streams that do not require closing is the minority, rather than majority.

  • File system handles
  • Operating-system owned resources, such as:
    • Sockets
    • Pipes
    • Operating-system managed shared memory (as opposed to JVM-managed memory)
  • Database connections

To put it bluntly,

  • It appears that array-backed streams are the only kind of streams that do not require explicit closing.

Does the cost-benefit analysis favor the inclusion of the close() method into the stream interface?

It seems so. For streams that do not require explicit closing, it is harmless to require it to provide a trivial close() method that does nothing.

Similar observation can be found in the C# language, where it is common to see interfaces that subtype from IDisposable.


Would the failure to include the close() method in the stream interface cause extraordinary harm to implementations that require it?

Yes. Not having it on the interface, or splitting it out to a second Closeable interface would cause extraordinary harm.

In the first code snippet below, suppose InputStream does not contain the close() method. Here is what the code would look like:

public void parseAndCloseStream(InputStream strm) throws IOException
{
    if (strm == null) { /* ... to avoid NPE inside finally */ }
    try
    {
        // read from stream
    }
    finally
    {
        if (strm instanceof Closeable)
        {
            Closeable c = (Closeable)strm;
            c.close();
        }
    }
}

In other words, because the omission implies that "not every InputStream is a Closeable", any consumer of any InputStream instance now has the additional responsibility to check whether the instance is indeed Closeable.

The try-with pattern would then also require more code, because you cannot use an InputStream there unless you can cast it into a Closeable.


Is it a violation of Interface Segregation Principle?

No.

  • If a method is fundamental to the operation for the majority of implementation, it makes sense to require it.
  • Likewise, if a method is cohesive with the rest of the methods in that interface (i.e. common-sense for its inclusion), it is not a violation.

Specifically, Interface Segregation Principle does not require:

  • Does not require an interface to be minimal; even though there are benefits for keeping an interface small and simple.
  • Does not require one to separate out all orthogonal facets of an interface, if doing so will cause more harm than good (great inconvenience).
  • May be this would help you programmers.stackexchange.com/questions/262706/… answer your first question. – overexchange Dec 20 '14 at 16:41
  • @overexchange I agree that traits would be more suitable for adding common peripheral behaviors to concrete implementations of an interface. – rwong Dec 20 '14 at 17:16
  • for your second question, there is no majority/minority. it is core and peripheral behaviour. close() is peripheral. – overexchange Dec 20 '14 at 17:24
  • @overexchange you have not yet provided any convincing argument that close() is peripheral and not core. – rwong Dec 20 '14 at 17:28
  • 1
    scenario of interface Closeable discussed in this query can be compared with interface ActionListener that is implemented by user subclasses of class JFrame but not JFrame itself. – overexchange Dec 21 '14 at 17:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.