简体   繁体   中英

In Java, does closing a parent input stream close its child, too?

FileInputStream fis = new FileInputStream(gzipFile);
GZIPInputStream gis = new GZIPInputStream(fis);
gis.close();
fis.close();

Is fis.close() necessary? Though I'm running this code and don't seem to get any errors.

You should see the implementation of GZIPInputStream.close() .

/**
 * Closes this input stream and releases any system resources associated
 * with the stream.
 * @exception IOException if an I/O error has occurred
 */
public void close() throws IOException {
    if (!closed) {
        super.close();  
        eos = true;
        closed = true;
    }
}

If you take a look at the constructor for GZIPInputStream , it looks like this:

/**
 * Creates a new input stream with the specified buffer size.
 * @param in the input stream
 * @param size the input buffer size
 * @exception IOException if an I/O error has occurred
 * @exception IllegalArgumentException if size is <= 0
 */
public GZIPInputStream(InputStream in, int size) throws IOException {
super(in, new Inflater(true), size);
    usesDefaultInflater = true;
        readHeader(in);
}

Watch the variable in . Notice how it is being passed to the super class which is InflaterInputStream in this case.

Now, if we have a look at the implementation of InflaterInputStream.close() method, we will find this:

/**
 * Closes this input stream and releases any system resources associated
 * with the stream.
 * @exception IOException if an I/O error has occurred
 */
public void close() throws IOException {
    if (!closed) {
        if (usesDefaultInflater)
            inf.end();
    in.close();
        closed = true;
    }
}

Clearly, in.close() is being called. So the wrapped (decorated) FileInputStream is also closed on the call to GZIPInputStream.close() . Thich makes calling fis.close() redundant.

This is one of those things that people need to clearly document. Unfortunately, GZIPInputStream overrides the close in its parent class and doesn't document what it does (poor documentation). But the odds are pretty high (even without looking at the code) that it will eventually call super.close() (and indeed we can see from adarshr's answer that it does, although you should never assume the implementation isn't going to change). If so, then we look at the docs for the parent class ( InflaterInputStream ). Unfortunately, it does exactly the same thing, overrides without documenting. But assume that it, too, calls super.close() at some point. Looking at its parent class ( FilterInputStream ) docs, it explicitly says it does a close on the in member, which is set via the constructor. (A separate assumption is that GZIPInputStream and InflaterInputStream pass on the constructor argument to their superclasses, but that's very likely indeed.)

So FilterInputStream tells you clearly that it's going to close the stream you provide to the constructor. The odds are pretty high the others are going to call super.close() , even though they're poorly documented, so yes, it should close it for you and you shouldn't have to do it yourself. But there are some assumptions involved.

Yes, it does. The javadoc says:

Closes this input stream and releases any system resources associated with the stream.

And the wrapped stream is definitely such a system resource.

Moreover, GZIPInputStream is a FilterInputStream, and the FilterInputStream javadoc says:

Closes this input stream and releases any system resources associated with the stream. This method simply performs in.close().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM