automatically closing a resource passed as an argument
Asked Answered
S

3

9

If I want to automatically close a resource passed as an argument, is there a more elegant solution than this?

void doSomething(OutputStream out) {

  try (OutputStream closeable = out) {
    // do something with the OutputStream
  }
}

Ideally, I'd like to have this resource closed automatically, without declaring another variable closeable that refers to the same object as out.

Aside

I realise that closing out within doSomething is considered a bad practice

Singlehandedly answered 14/8, 2018 at 9:17 Comment(5)
I think the doSomething method should not close the input stream itselft. The caller should take care of it.Barroom
I believe java 9 allows that (the out variable is effectively final). But there's a risk for method parameters, I think.Boar
@oleg.cherednik It does implement AutoCloseable, from the Javadoc: _"All Implemented Interfaces: Closeable, Flushable, AutoCloseable". It directly implements Closeable which extends AutoCloseable.Contact
@MarkRotteveel I can see another picture in my sources. Probably it depends on JVM version.Cloninger
@oleg.cherednik Only if you're using Java 6 or lower. AutoCloseable was introduced in Java 7. Or maybe you've overlooked that Closeable is a sub-interface of AutoCloseable).Contact
C
5

With Java 9 and higher, you can do

void doSomething(OutputStream out) {
  try (out) {
    // do something with the OutputStream
  }
}

This is only allowed if out is final or effectively final. See also the Java Language Specification version 10 14.20.3. try-with-resources.

Contact answered 14/8, 2018 at 9:37 Comment(2)
I'm using Java 8 at the moment, but good to know there's a more elegant solution in the next versionPreengage
@Singlehandedly The only thing in Java 8 that would make your current code (as shown) shorter is replacing OutputStream closeable by Closeable closeable, but I think that is grasping at straws and makes the intent even less obvious.Contact
C
3

I use Java 8 and it does not support Resource Reference. What about create universal method that accepts Closable and payload:

public static <T extends Closeable> void doAndClose(T out, Consumer<T> payload) throws Exception {
    try {
        payload.accept(out);
    } finally {
        out.close();
    }
}

Client code could look like this:

OutputStream out = null;

doAndClose(out, os -> {
    // do something with the OutputStream
});

InputStream in = null;

doAndClose(in, is -> {
    // do something with the InputStream
});
Cloninger answered 14/8, 2018 at 9:48 Comment(2)
Can you include an example how this would be applied (eg as a replacement in the doSomething method)?Contact
This removes the potential confusion that might arise from 2 references to the closeable resource being accessible within the payload body. It should probably accept a Consumer<? super T>, though.Vertical
C
-4
void doSomething(OutputStream out) {
  try {
    // do something with the OutputStream
  }
  finally {
    org.apache.commons.io.IOUtils.closeQuietly(out);
  }
}
Chesson answered 14/8, 2018 at 9:28 Comment(1)
From the JavaDocs of org.apache.commons.io.IOUtils.ArrayUtils.closeQuietly: "Deprecated. As of 2.6 removed without replacement. Please use the try-with-resources statement or handle suppressed exceptions manually."Vertical

© 2022 - 2024 — McMap. All rights reserved.