173

I'm in the process of learning Java and I cannot find any good explanation on the implements Closeable and the implements AutoCloseable interfaces.

When I implemented an interface Closeable, my Eclipse IDE created a method public void close() throws IOException.

I can close the stream using pw.close(); without the interface. But, I cannot understand how I can implement theclose() method using the interface. And, what is the purpose of this interface?

Also I would like to know: how can I check if IOstream was really closed?

I was using the basic code below

import java.io.*;

public class IOtest implements AutoCloseable {

public static void main(String[] args) throws IOException  {

    File file = new File("C:\\test.txt");
    PrintWriter pw = new PrintWriter(file);

    System.out.println("file has been created");

    pw.println("file has been created");

}

@Override
public void close() throws IOException {


}
Kirby
  • 15,127
  • 10
  • 89
  • 104
malas
  • 1,887
  • 3
  • 13
  • 7
  • 5
    I think all has already been said, but maybe you are interested in the following article about try on ressources: http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html . This might also be helpful to understand the given answers. – crusam Oct 30 '12 at 14:51

6 Answers6

242

AutoCloseable (introduced in Java 7) makes it possible to use the try-with-resources idiom:

public class MyResource implements AutoCloseable {

    public void close() throws Exception {
        System.out.println("Closing!");
    }

}

Now you can say:

try (MyResource res = new MyResource()) {
    // use resource here
}

and JVM will call close() automatically for you.

Closeable is an older interface. For some reason To preserve backward compatibility, language designers decided to create a separate one. This allows not only all Closeable classes (like streams throwing IOException) to be used in try-with-resources, but also allows throwing more general checked exceptions from close().

When in doubt, use AutoCloseable, users of your class will be grateful.

informatik01
  • 16,038
  • 10
  • 74
  • 104
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • 133
    The reason is simple: `Closeable.close()` throws `IOException`. A lot of `close()` methods that could benefit of try-with-resources throw other checked exceptions (eg `java.sql.Connection.close()` so `AutoCloseable.close()` throws `Exception`. Changing the existing `Closeable` contract would break all existing applications/library relying on the contract that `close()` only throws `IOException` and not all (checked) exceptions. – Mark Rotteveel Oct 30 '12 at 14:49
  • 4
    @MarkRotteveel: +1, thanks. I corrected my answer to reflect your suggestions and comments. – Tomasz Nurkiewicz Oct 30 '12 at 14:57
  • 19
    And also: `Closeable.close()` is required to be idempotent. `AutoCloseable.close()` is not, although it is still strongly recommended. – Lukas Eder Jan 25 '14 at 17:00
  • 2
    Also, don't use the default `public void close( ) throws Exception` -- use a more specific exception if you can (e..g IOException) – gerardw Nov 15 '14 at 20:23
  • Except this breaks backwards compatibility, because things that used to be Closable (like `javax.sql.Connection`) are now *only* AutoClosable, so won't work with libraries (like commons-io) anymore, because they only support Closable (Because they need to compile with non-Java 7 JDK) . – Mikkel Løkke Feb 20 '15 at 11:46
  • 1
    "When in doubt, use `AutoCloseable`, users of your class will be grateful." Wouldn't users prefer `Closeable`, since that guarantees idempotence and throws the more specific IOException? – Andrew McKinlay Apr 20 '15 at 00:11
  • 3
    `Closeable` does not *guarantee* idempotence. It *requires* idempotence in a user's implementation of the `close()` method. And whether `IOException` is more specific/appropriate depends on the use case. – xdhmoore Jul 15 '15 at 22:33
  • 1
    "When in doubt, use AutoCloseable, users of your class will be grateful" - this doen't give any gain since older `Closable` was retrofitted to implement `AutoCloseable` too. – Vadzim Jul 28 '15 at 14:14
  • 2
    You can also use Closable in a try-with-resources, as Closable is a subinterface of AutoClosable – Daniel Jan 18 '18 at 03:50
  • This is not true for java 8 at least, `closeable` also works with the try-with-resources idiom – Ohad Bitton Nov 19 '19 at 11:28
92

Closeable extends AutoCloseable, and is specifically dedicated to IO streams: it throws IOException instead of Exception, and is idempotent, whereas AutoCloseable doesn't provide this guarantee.

This is all explained in the javadoc of both interfaces.

Implementing AutoCloseable (or Closeable) allows a class to be used as a resource of the try-with-resources construct introduced in Java 7, which allows closing such resources automatically at the end of a block, without having to add a finally block which closes the resource explicitly.

Your class doesn't represent a closeable resource, and there's absolutely no point in implementing this interface: an IOTest can't be closed. It shouldn't even be possible to instantiate it, since it doesn't have any instance method. Remember that implementing an interface means that there is a is-a relationship between the class and the interface. You have no such relationship here.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • 9
    Just implement **Closable** for streams-related classes, and **AutoClosable** for others which requires autoclose feature. – lospejos Jul 13 '16 at 15:13
47

It seems to me that you are not very familiar with interfaces. In the code you have posted, you don't need to implement AutoCloseable.

You only have to (or should) implement Closeable or AutoCloseable if you are about to implement your own PrintWriter, which handles files or any other resources which needs to be closed.

In your implementation, it is enough to call pw.close(). You should do this in a finally block:

PrintWriter pw = null;
try {
   File file = new File("C:\\test.txt");
   pw = new PrintWriter(file);
} catch (IOException e) {
   System.out.println("bad things happen");
} finally {
   if (pw != null) {
      try {
         pw.close();
      } catch (IOException e) {
      }
   }
}

The code above is Java 6 related. In Java 7 this can be done more elegantly (see this answer).

kc2001
  • 5,008
  • 4
  • 51
  • 92
Kai
  • 38,985
  • 14
  • 88
  • 103
  • 3
    Why only with a `PrintWriter`? Especially `AutoClosable` objects can be used in many more circumstances than just `PrintWriter`s... – glglgl Jan 26 '15 at 14:53
  • 3
    You are absolutely right. The question was about `PrintWriter` so I mentioned it to be more specific. – Kai Jan 26 '15 at 19:48
  • 7
    Why describe the situation for Java 6 in the context of `AutoCloseable`? Better show a `try-with-resources` instead … – ᴠɪɴᴄᴇɴᴛ Dec 01 '17 at 14:09
10

Here is the small example

public class TryWithResource {

    public static void main(String[] args) {
        try (TestMe r = new TestMe()) {
            r.generalTest();
        } catch(Exception e) {
            System.out.println("From Exception Block");
        } finally {
            System.out.println("From Final Block");
        }
    }
}



public class TestMe implements AutoCloseable {

    @Override
    public void close() throws Exception {
        System.out.println(" From Close -  AutoCloseable  ");
    }

    public void generalTest() {
        System.out.println(" GeneralTest ");
    }
}

Here is the output:

GeneralTest 
From Close -  AutoCloseable  
From Final Block
Lova Chittumuri
  • 2,994
  • 1
  • 30
  • 33
10

Recently I have read a Java SE 8 Programmer Guide ii Book.

I found something about the difference between AutoCloseable vs Closeable.

The AutoCloseable interface was introduced in Java 7. Before that, another interface existed called Closeable. It was similar to what the language designers wanted, with the following exceptions:

  • Closeable restricts the type of exception thrown to IOException.
  • Closeable requires implementations to be idempotent.

The language designers emphasize backward compatibility. Since changing the existing interface was undesirable, they made a new one called AutoCloseable. This new interface is less strict than Closeable. Since Closeable meets the requirements for AutoCloseable, it started implementing AutoCloseable when the latter was introduced.

Dmitriy Fialkovskiy
  • 3,065
  • 8
  • 32
  • 47
Arvind Katte
  • 995
  • 2
  • 10
  • 20
  • 1
    Instead of saying that "This new interface is less strict than `Closeable`", I'd suggest saying "This new interface can be used in more general contexts, where the exception thrown during closing is not necessarily an IOException". In the Java universe, being "less strict" has a negative vibe about it. – fountainhead Sep 08 '19 at 04:47
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();
    }

}

Please refer to the docs.

ItamarG3
  • 4,092
  • 6
  • 31
  • 44
inder
  • 303
  • 2
  • 12