Java Language Pitfall - Not checking if an I/O stream isn't even initialized when closing it


Example

To prevent memory leaks, one should not forget to close an input stream or an output stream whose job is done. This is usually done with a try-catch-finally statement without the catch part:

void writeNullBytesToAFile(int count, String filename) throws IOException {
    FileOutputStream out = null;
    try {
        out = new FileOutputStream(filename);
        for(; count > 0; count--)
            out.write(0);
    } finally {
        out.close();
    }
}

While the above code might look innocent, it has a flaw that can make debugging impossible. If the line where out is initialized (out = new FileOutputStream(filename)) throws an exception, then out will be null when out.close() is executed, resulting in a nasty NullPointerException!

To prevent this, simply make sure the stream isn't null before trying to close it.

void writeNullBytesToAFile(int count, String filename) throws IOException {
    FileOutputStream out = null;
    try {
        out = new FileOutputStream(filename);
        for(; count > 0; count--)
            out.write(0);
    } finally {
        if (out != null)
            out.close();
    }
}

An even better approach is to try-with-resources, since it'll automatically close the stream with a probability of 0 to throw an NPE without the need of a finally block.

void writeNullBytesToAFile(int count, String filename) throws IOException {
    try (FileOutputStream out = new FileOutputStream(filename)) {
        for(; count > 0; count--)
            out.write(0);
    }
}