3

I was looking at Java Serialization articles and stumbled a number of times across examples where the streams are closed in the try block instead of in a finally block. Can someone explain to me why is that?

Example:

import java.io.*;
public class DeserializeDemo {

    public static void main(String [] args) {
      Employee e = null;
      try {
         FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
         ObjectInputStream in = new ObjectInputStream(fileIn);
         e = (Employee) in.readObject();
         in.close();
         fileIn.close();
      } catch(IOException i) {
         i.printStackTrace();
         return;
      } catch(ClassNotFoundException c) {
         System.out.println("Employee class not found");
         c.printStackTrace();
         return;
      }

      System.out.println("Deserialized Employee...");
      System.out.println("Name: " + e.name);
      System.out.println("Address: " + e.address);
      System.out.println("SSN: " + e.SSN);
      System.out.println("Number: " + e.number);
   }
}

Source: http://www.tutorialspoint.com/java/java_serialization.htm

Tom
  • 16,842
  • 17
  • 45
  • 54
Mr. Nicky
  • 1,519
  • 3
  • 18
  • 34

8 Answers8

7

The try-with-resources Statement

The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.

The following example reads the first line from a file. It uses an instance of BufferedReader to read data from the file. BufferedReader is a resource that must be closed after the program is finished with it:

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

In this example, the resource declared in the try-with-resources statement is a BufferedReader. The declaration statement appears within parentheses immediately after the try keyword. The class BufferedReader, in Java SE 7 and later, implements the interface java.lang.AutoCloseable. Because the BufferedReader instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly (as a result of the method BufferedReader.readLine throwing an IOException).

Prior to Java SE 7, you can use a finally block to ensure that a resource is closed regardless of whether the try statement completes normally or abruptly. The following example uses a finally block instead of a try-with-resources statement:

static String readFirstLineFromFileWithFinallyBlock(String path)
                                                     throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}

Source =>http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

Roushan
  • 4,074
  • 3
  • 21
  • 38
2

From documentation:

The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs.

The runtime system always executes the statements within the finally block regardless of what happens within the try block. So it's the perfect place to perform cleanup.

So it means if you have some connection, stream or some other resources opened you have to be sure that they will be closed after your code block will be executed.

To avoid such ugly blocks you can use utility methods:

public void close(Closeable closeable) {
    if (closeable != null) {
        try {
            closeable.close();
        } catch (IOException ex) {
            // handle block
        }
    }
}

Since Java 8 (but it is not required) you can provide your own Exception handler with closing resource:

public void close(Closeable closeable, Consumer<? extends Throwable> handler) {
    if (closeable != null) {
        try {
            closeable.close();
        } catch (IOException ex) {
            handler.accept(ex);
        }
    }
}

Also, just for knowledge, there are two cases when finally block is not called. It means that in most cases it will be called.

Community
  • 1
  • 1
Andrii Abramov
  • 10,019
  • 9
  • 74
  • 96
2

If you are Java 7 or above…

Don't close in finally block

The close method can throw an IOException and FileInputStream/ObjectInputStream can be null. When you use .close in finally, you must check null and try/catch again.

Use "try-with-resources Statement" instead

Using try-with-resources your code looks like this:

try(
    FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
    ObjectInputStream in = new ObjectInputStream(fileIn)
) {
    e = (Employee) in.readObject();
    // in.close();
    // fileIn.close();
} 

The try-with-resources syntax guarantees the resources implementing AutoCloseable interface will be closed automatically. So you don't need to call a close method on your code.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
myx4play
  • 111
  • 3
1

You should close connection in finally. As finally always going to execute whether it goes in try or catch.

Also we need to close every connection once it created.

try{
  // statements 
}catch (){
 // statements 
}
finally {
    in.close();
    fileIn.close();
}
1

I was looking at Java Serialization articles and stumbled a number of times across examples where the streams are closed in the try block instead of in a finally block.

Examples that do it that way are poor examples. While closing a stream within a try block will work for simple one-shot examples, doing this in a case where the code might be executed multiple times is liable to lead to resource leaks.

The other Answers to this Question do a good job of explaining the right way(s) to close streams.

Can someone explain to me why is that?

It comes down to poor quality control on the tutorial sites; i.e. inadequate code reviewing.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Yeah, I've noticed a lot of mistakes on that same tutorial site. – Mr. Nicky Sep 19 '16 at 12:07
  • Can I suggest that you look at the StackOverflow Documentation site as well / instead? (See the "Documentation (beta)" button near the top of this page?) We also have some "quality control issues" at the moment ... but we are working on that. – Stephen C Sep 19 '16 at 12:11
  • Wow, thanks for the recommendation! I never knew there was such a thing :D – Mr. Nicky Sep 19 '16 at 12:14
1

The accepted answer certainly has a bug.

The close method can throw an IOException too. If this happens when in.close is called, the exception prevents fileIn.close from getting called, and the fileIn stream remains open.

It can implemented as below when multiple streams are involved:

} finally {
 if ( in != null) {
  try { in .close();
  } catch (IOException ex) {
   // There is nothing we can do if close fails
  }
 }
 if (fileIn != null) {
  try {
   fileIn.close();
  } catch (IOException ex) {
   // Again, there is nothing we can do if close fails
  }
 }
}

Or, take advantage of Closeable Interface

} finally {
  closeResource(in);
  closeResource(fileIn);
}

Method:

private static void closeResource(Closeable c) {
 if (c != null) {
  try {
   c.close();
  } catch (IOException ex) {
   // There is nothing we can do if close fails
  }
 }
}
Vivek Pratap Singh
  • 9,326
  • 5
  • 21
  • 34
0

You should close in finally block.

It's a bad habit to close in try block.

  try { 
     e = (Employee) in.readObject();   //Possibility of exception 
  } catch(IOException i) { 

  } catch(ClassNotFoundException c) { 

  } finally {
     in.close();
     fileIn.close();
  }

When someone is writing a code by knowing it will throw an exception,he/she has to close the opened resources

Prasanna Kumar H A
  • 3,341
  • 6
  • 24
  • 52
  • This code certainly has a bug.The close method can throw an IOException too.If this happens when in.close is called, the exception prevents fileIn.close from getting called, and the fileIn stream remains open. – Vivek Pratap Singh Aug 06 '18 at 19:34
0

You should always close in a finally block. However, you can use try with resources.

Here's the link: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

static String readFirstLineFromFile(String path) throws IOException {
 try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
  }
}