Reputation: 1669
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
Upvotes: 3
Views: 10461
Reputation: 131
If you are Java 7 or above…
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.
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.
Upvotes: 2
Reputation: 9974
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
}
}
}
Upvotes: 1
Reputation:
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();
}
}
Upvotes: 0
Reputation: 719336
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.
Upvotes: 1
Reputation: 10773
From documentation:
The
finally
block always executes when thetry
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 thetry
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.
Upvotes: 2
Reputation: 4440
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
Upvotes: 7
Reputation: 3431
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
Upvotes: 0
Reputation: 52
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();
}
Upvotes: 1