Resource
Resource is an object that must be closed after its operations are completed. It refers to an external entity or component that your program interacts with and that typically requires careful management. Many such resources must be explicitly closed after use to free up the underlying resource, preventing potential issues like memory leaks or file locks. Common examples include:
- File Handles: Represent access to files on the disk.
- Database Connections: Connections to a database server. If database connections are not closed, the connection pool can be exhausted, leading to failures in acquiring new database connections.
- Network Connections: Sockets or streams used for communication over a network.
- Streams: Input or output streams used for reading from or writing to data sources.
Resource Handling
Resource handling refers to managing system resources like file streams, database connections, network connections, etc., which need to be closed after use to free up system resources. Failure to do so can lead to resource leaks (memory used by these resources is not released back to the system), which can cause performance degradation and application crashes.
try-with-resources Statement
The try-with-resources
statement is a try
statement that declares one or more resources. The try-with-resources
statement ensures that each resource is closed at the end of the statement. In Java, a resource must implement the AutoCloseable
interface to be used with try-with-resources.
AutoCloseable Interface:
- The
AutoCloseable
interface defines theclose()
method, which is called automatically at the end of the try block. - Any class that implements
AutoCloseable
can be used as a resource in try-with-resources.
static String readFirstLineFromFile(String path) throws IOException {
try (FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr)) {
return br.readLine();
}
}
In this example, the resources declared in the try-with-resources
statement are a FileReader
and a BufferedReader
. The declaration statements of these resources appear within parentheses immediately after the try
keyword. The classes FileReader
and BufferedReader
, in Java SE 7 and later, implement the interface java.lang.AutoCloseable
. Because the FileReader
and BufferedReader
instances are declared in a try-with-resource
statement, they will be closed regardless of whether the try
statement completes normally or abruptly.
Alternate using try-catch-finally
static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr);
try {
return br.readLine();
} finally {
br.close();
fr.close();
}
}
Try-with-Resources with Multiple Resources
Multiple resources can be declared within the parentheses of the try statement, separated by semicolons.
try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"));
PrintWriter writer = new PrintWriter(new FileWriter("output.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
writer.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
Custom Resource with AutoCloseable
- You can create your own classes that implement
AutoCloseable
to take advantage of try-with-resources.
class CustomResource implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("CustomResource closed.");
}
public void use() {
System.out.println("Using CustomResource.");
}
}
public class CustomResourceExample {
public static void main(String[] args) {
try (CustomResource resource = new CustomResource()) {
resource.use();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Resource Closing Order
Resources are closed in the reverse order of their declaration.
try (Resource1 res1 = new Resource1();
Resource2 res2 = new Resource2()) {
// Use resources
} catch (Exception e) {
e.printStackTrace();
}
// res2.close() is called before res1.close()
Catch and Finally with Try-With-Resources
- The
catch
andfinally
blocks can be used with try-with-resources just as with regular try-catch-finally constructs.
try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
// Use the resource
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("This is the finally block.");
}