1

Will this release my resources after being used?

    InputStream inputStream;
    try (InputStream unverifiedStream = connection.getInputStream()){
        inputStream = unverifiedStream;
    } catch (Exception e) {
        e.printStackTrace();
    }
    //and use stream here to do other stuff with other streams
  • @FoggyDay doesn't this try-with-resources automatically closes it for you? –  Oct 26 '14 at 03:16

3 Answers3

3

That will release your resources (close the stream) and leave you talking to a closed stream.

The assignment to inputStream does not copy the stream object. It copies the reference to the stream object. You now have two different ways to talk to the same object.

candied_orange
  • 7,036
  • 2
  • 28
  • 62
  • So I can not use the stream anymore? Is it better to use the finally style in this case? –  Oct 26 '14 at 03:17
  • 2
    Not if you need it to be open. No. – candied_orange Oct 26 '14 at 03:19
  • Actually I'm not sure what you mean by the finally style. There is a perfectly valid style of using the stream inside the try body where other methods can throw other exceptions. Finally is for code that must be run regardless of an exception being thrown. You just don't need it to close what you open inside try's ()'s – candied_orange Oct 26 '14 at 03:30
  • I mean to close the stream in the catch block without try-with-resources. So I can keep using it. –  Oct 26 '14 at 03:33
  • @user2898147 see my answer for more details. My guess is that you refer to the classical pre-Java 7 programming idiom in which you open resources before `try` and close them in `finally`; a try-with-resources statement obsoletes this idiom. Prior to Java 7 you'd want to use Guava's Closer – fge Oct 26 '14 at 03:33
  • Pre java 7 we have a perfectly fine idiom for closing in the finally (not the catch) without using Guava. With java 7 you can still do that or use the try() trick. They both work. The try() trick is less typing and easier on the eyes. None of these solutions allow the stream to wander off into other code to live an independent life. It was born here. It must die here. – candied_orange Oct 26 '14 at 03:37
  • @CandiedOrange "perfectly fine" as long as it is _one_ resource! If more than one you are doomed... Hence `Closer` – fge Oct 26 '14 at 03:38
  • This is also fine. Simply close in reverse order of allocation. You need to be doing some seriously stupid multithreaded allocation to make that a problem. Go read up on the dining philosophers if you want to be paranoid. – candied_orange Oct 26 '14 at 03:42
  • @CandiedOrange you are contradicting yourself. Hint: before `try`, open r1 then r2; in `finally` close r2 then r1. Now, what happens if you successfully open r1 but not r2? You never get to close r1. `Closer` avoids this problem. – fge Oct 26 '14 at 03:46
  • The idiom was to guard every close with an if (resource1 != null) so I don't care what succeeded or failed. I try to close them all in reverse order. It takes a bit of typing but it works. It's been doing so for years. You can see it here: http://stackoverflow.com/questions/2699209/java-io-ugly-try-finally-block – candied_orange Oct 26 '14 at 03:51
1

Since you are using a try-with-resource statement, and if by "released" you mean "closed" then yes.

Any instance implementing AutoCloseable opened in a try-with-resources statement is .close()d right before catch, so in your case unverifiedStream will be closed before you catch Exception.

It should also be noted that Closeable extends AutoCloseable, so all existing classes implementing Closeable will "magically" work within a try-with-resources statement.

Sample code:

public final class AutoCloseableExample
{
    private static final class Foo
        implements AutoCloseable
    {
        @Override
        public void close()
            throws IOException
        {
            System.out.println("foo");
            throw new IOException();
        }
    }

    public static void main(final String... args)
    {
        try (
            final Foo foo = new Foo();
        ) {
            System.out.println("try block");
        } catch (IOException ignored) {
            System.out.println("exception!");
        } finally {
            System.out.println("finally block");
        }
    }
}

Output:

try block
foo
exception!
finally block

Side note: you should not catch Exception since this also catches all unchecked exceptions (ie, RuntimeException and derivates). Catch more specific exceptions instead.

fge
  • 119,121
  • 33
  • 254
  • 329
  • Thank you very much for explaining it in these tiny details. I totally get it now. –  Oct 26 '14 at 03:39
  • @user2898147 you're welcome! Also note that you have to _declare_ your resource inside the try-with-resources statement; that is, you cannot do `Closeable c; try ( c = something() ) { ... }` – fge Oct 26 '14 at 03:41
0

I haven't tried this, but I don't think it will compile if you try to use inputStream after the try-catch block, because inputStream won't be initialized if connection.getInputStream() throws an exception. Your catch block should assign a value or introduce a different flow of control to take care of that possibility.

If the try block completes normally, inputStream will refer to a closed stream outside the try-catch block, and most implementations will throw an exception on any operation you attempt on the stream.

erickson
  • 265,237
  • 58
  • 395
  • 493