Week 83 — What is `AutoCloseable` and why is it useful?

Question of the Week #83
What is AutoCloseable and why is it useful?
6 Replies
Eric McIntyre
Eric McIntyre5mo ago
If a class implements AutoCloseable, its objects should be "closed" when it isn't needed any more. This is the case for files, network sockets, database connections or similar resources. Once the close() method is called, the class is typically no longer usable. To implement this interface, the class needs to override the close() method:
public class MyAutoCloseable implements AutoCloseable {
private boolean open = true;
public MyAutoCloseable(){
System.out.println("created MyAutoCloseable - this should be closed when no longer needed");
}
public void doSomething() throws IOException{
if(!open){
throw new IOException("This object has been closed and can no longer be used.");
}
//do some work here
}
@Override
public void close(){
if(open){
open = false;
System.out.println("MyAutoCloseable has been closed.");
}
}
}
public class MyAutoCloseable implements AutoCloseable {
private boolean open = true;
public MyAutoCloseable(){
System.out.println("created MyAutoCloseable - this should be closed when no longer needed");
}
public void doSomething() throws IOException{
if(!open){
throw new IOException("This object has been closed and can no longer be used.");
}
//do some work here
}
@Override
public void close(){
if(open){
open = false;
System.out.println("MyAutoCloseable has been closed.");
}
}
}
Eric McIntyre
Eric McIntyre5mo ago
Objects implementing AutoCloseable can be closed using a try-with-resources statement:
try(MyAutoCloseable myObject = new MyAutoCloseable()){
myObject.doSomething();
}
try(MyAutoCloseable myObject = new MyAutoCloseable()){
myObject.doSomething();
}
With this, the JVM makes sure the close() method is called at the end of the try-block, no matter whether it completed successfully or with an exception. Alternatively, it would also possible to call close() manually in a try-finally block:
MyAutoCloseable myObject = new MyAutoCloseable();
try{
myObject.doSomething();
}finally{
myObject.close();
}
//myObject.doSomething();//IOException: MyAutoCloseable has been closed.
MyAutoCloseable myObject = new MyAutoCloseable();
try{
myObject.doSomething();
}finally{
myObject.close();
}
//myObject.doSomething();//IOException: MyAutoCloseable has been closed.
It is also possible to close multiple objects in a try-with resource block:
try(MyAutoCloseable myFirstObject = new MyAutoCloseable();
MyAutoCloseable anotherObject = new MyAutoCloseable()){
myObject.doSomething();
}
try(MyAutoCloseable myFirstObject = new MyAutoCloseable();
MyAutoCloseable anotherObject = new MyAutoCloseable()){
myObject.doSomething();
}
This makes sure that both myFirstObject and anotherObject, are closed even if the second one isn't created due to an exception (then only the first one would be closed) or if closing the first one results in an exception. Because of that, a try-with-resources block is the safest way to close resources.
📖 Sample answer from dan1st
Eric McIntyre
Eric McIntyre5mo ago
I know only by the example of a Class that needs to be closed, and it's useful to use on a try with resources, like:
public class CloseableClass implements AutoCloseable {

private BufferedOutputStream output;

public CloseableClass() {
this.output = new BufferedOutputStream(System.out);
}

public void print(String message) throws IOException {
this.output.write(message.getBytes(StandardCharsets.UTF_8));
}

@Override
public void close() throws Exception {
this.output.close();
}
}
public class CloseableClass implements AutoCloseable {

private BufferedOutputStream output;

public CloseableClass() {
this.output = new BufferedOutputStream(System.out);
}

public void print(String message) throws IOException {
this.output.write(message.getBytes(StandardCharsets.UTF_8));
}

@Override
public void close() throws Exception {
this.output.close();
}
}
so I can use:
try (var out = new CloseableClass()) {
out.print("Message");
} catch (Exception e) {
e.printStackTrace();
}
try (var out = new CloseableClass()) {
out.print("Message");
} catch (Exception e) {
e.printStackTrace();
}
and it will be closed even if throws exception
Submission from viniciuspdionizio
Eric McIntyre
Eric McIntyre5mo ago
A class which has some sort of open resource which should be closed after use. It allows you to instantiate it in a try, use it within that block, and then it’ll be automatically closed when you exit that block
Submission from elspon
Eric McIntyre
Eric McIntyre5mo ago
AutoCloseable is a very simple interface that defines a close method. It is designed to be implemented by classes that allocate resources that must be cleaned up when they are no longer used, such as a network socket, database connection, or file I/O stream. It's utility comes from being a "magic" interface, with a special relationship to the try-with-resources statement. Any class that implements AutoCloseable can be used in a try block to automatically clean up the allocated resources. For instance, if we have a MyScarceResource class that implements AutoCloseable, then we can do the following:
try (MyScarceResource res = new MyScarceResource()) {
// Do something with `res`
} catch (SomeResourceException e) {
e.printStackTrace();
}
try (MyScarceResource res = new MyScarceResource()) {
// Do something with `res`
} catch (SomeResourceException e) {
e.printStackTrace();
}
Notably, there is no need to call the close method manually in a finally block, since it will be called automatically at the end of the try block (before any catch or finally blocks are entered).
Eric McIntyre
Eric McIntyre5mo ago
Another important detail is that the close method itself can throw an exception, in addition to exceptions that might be generated within the try block. In order to prevent undefined behavior, or a situation where an error gets lost, a "suppressed exception" mechanism was added. If the try block throws an exception, and then the close call throws an exception, the original exception from the try will be handled (e.g. in a catch block or propagated out of the method). However, the Throwable::getSuppressed() method can be called on the exception to get access to any exceptions thrown from the close call.
⭐ Submission from dangerously_casual
Want results from more Discord servers?
Add your server