Closeableを実装するか、AutoCloseableを実装します


128

私はJavaを学習してimplements Closeableいるimplements AutoCloseable最中です。およびのインターフェースについての適切な説明はありません。

を実装するinterface Closeableと、Eclipse IDEがメソッドを作成しましたpublic void close() throws IOException

pw.close();インターフェイスなしでを使用してストリームを閉じることができます。しかし、close()インターフェイスを使用してメソッドを実装する方法を理解できません。そして、このインターフェースの目的は何ですか?

また、知りたいのですIOstreamが、本当に閉じているかどうかを確認するにはどうすればよいですか

以下の基本的なコードを使用していた

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 {


}

2
私はすべてがすでに述べられていると思いますが、多分あなたはリソースの試用に関する次の記事に興味があります:docs.oracle.com/javase/tutorial/essential/exceptions/…。これは、与えられた答えを理解するのにも役立ちます。
crusam

回答:


40

あなたはインターフェースにあまり慣れていないようです。投稿したコードでは、を実装する必要はありませんAutoCloseable

実装する必要がある(またはする必要がある)CloseableAutoCloseable、独自のを実装しようとしているPrintWriter場合にのみ、ファイルまたはその他の閉じる必要のあるリソースを処理します。

実装では、を呼び出すだけで十分pw.close()です。これはfinallyブロックで行う必要があります。

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) {
      }
   }
}

上記のコードはJava 6に関連しています。Java 7では、これをよりエレガントに行うことができます(この回答を参照)。


3
どうしてPrintWriter?特にAutoClosableオブジェクトは、PrintWriters 以外の多くの状況で使用できます...
glglgl

3
あなたは、絶対に正しい。質問があったPrintWriterので、もっと具体的に言った。
カイ

7
なぜJava 6の状況を説明するのAutoCloseableですか?ベター示しtry-with-resources代わりに...
ᴠɪɴᴄᴇɴᴛ

191

AutoCloseable(Java 7で導入)は、try-with-resourcesイディオムを使用できるようにします。

public class MyResource implements AutoCloseable {

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

}

今あなたは言うことができます:

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

JVMがclose()自動的に呼び出します。

Closeable 古いインターフェースです。 何らかの理由で下位互換性を維持するために、言語設計者は別のものを作成することを決定しました。これにより、すべてのCloseableクラス(ストリームスローなどIOException)をtry-with-resourcesで使用できるだけでなく、からのより一般的なチェック済み例外をスローすることもできますclose()

疑わしい場合は、を使用してAutoCloseable、クラスのユーザーに感謝してください。


107
理由は簡単です:Closeable.close()スローしますIOException。多くのclose()資源がトライして、他のチェック例外を投げるの利益を得ることができる方法には、(例えば、java.sql.Connection.close()とてもAutoCloseable.close()スローException既存の変更。Closeableすべての既存のアプリケーションを壊す契約を/ライブラリがその契約に頼るclose()だけではスローIOExceptionすべて(チェック)例外をしていない。
マークRotteveel

4
@MarkRotteveel:+1、ありがとう。私はあなたの提案やコメントを反映するように私の答えを修正しました。
Tomasz Nurkiewicz 2012年

9
またCloseable.close()、べき等である必要があります。AutoCloseable.close()それはまだ強くお勧めしますが、そうではありません。
Lukas Eder 2014年

2
また、デフォルトを使用しないでください。public void close( ) throws Exception可能であれば、より具体的な例外を使用してください(例:IOException)
gerardw

3
Closeableべき等を保証するものではありませ。それは必要とのユーザーの実装で冪等close()の方法を。そして、IOExceptionより具体的/適切かどうかは、ユースケースによって異なります。
xdhmoore 2015

71

Closeableextends AutoCloseable、特にIOストリーム専用です。これは、ExceptionではなくIOExceptionをスローし、べき等ですが、AutoCloseableはこの保証を提供しません。

これはすべて、両方のインターフェースのjavadocで説明されています。

AutoCloseable(またはCloseable)を実装すると、Java 7で導入されたtry-with-resourcesコンストラクトのリソースとしてクラスを使用できるようになります。これにより、ブロックの最後にそのようなリソースを自動的に閉じることができます。閉じるfinallyブロックを追加する必要はありません。リソースを明示的に。

クラスがクローズ可能なリソースを表していないため、このインターフェイスを実装してもまったく意味がありません。IOTestをクローズすることはできません。インスタンスメソッドがないため、インスタンス化することもできません。インターフェースを実装するということは、クラスとインターフェースの間にis-a関係があるということを覚えておいてください。ここにはそのような関係はありません。


5
ただ、実装開閉可能にストリーム関連クラスのために、そしてAutoClosableオートクローズ機能が必要です他の人のために。
lospejos

7

ここに小さな例があります

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 ");
    }
}

出力は次のとおりです。

GeneralTest 
From Close -  AutoCloseable  
From Final Block

そのような短いコードの試験プロジェクトが不要になるように、出力も書き込むことをお勧めします。
raxetul

close()メソッドでは、リソースを明示的に閉じる必要はありませんか?たぶんprint文しかありません。
Shailesh Waghmare

@ShaileshWaghmareはいそうです。しかし、テストの目的で、コードスニップで言及しました。
Lova Chittumuri

@LovaChittumuri this.close()自動的に呼び出されるので、コードのようになりますか?(念のため)
Shailesh Waghmare

@shailesh Waghmare私をテストしますか?
Lova Chittumuri

6

try-with-resources声明。

try-with-resources statementあるtry1つ以上のリソースを宣言する声明。A resourceは、プログラムの終了後に閉じる必要があるオブジェクトです。try-with-resources statement各リソースは、文の最後に閉じられていることを保証します。を実装するjava.lang.AutoCloseableすべてのオブジェクトを含む、を実装するすべてのオブジェクトをjava.io.Closeableリソースとして使用できます。

次の例では、ファイルから最初の行を読み取ります。BufferedReaderファイルからデータを読み取るためにのインスタンスを使用します。BufferedReaderプログラムが終了した後に閉じる必要があるリソースです。

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

この例では、try-with-resourcesステートメントで宣言されたリソースはBufferedReaderです。宣言ステートメントは、tryキーワードの直後の括弧内に表示されます。このクラスBufferedReaderは、Java SE 7以降では、インターフェースを実装しますjava.lang.AutoCloseableBufferedReaderインスタンスはtry-with-resourceステートメントで宣言されているため、tryステートメントが正常に完了したか、または(メソッドがをBufferedReader.readLineスローした結果として)突然完了したかに関係なく、インスタンスは閉じられIOExceptionます。

Java SE 7より前のバージョンでは、finallyブロックを使用して、tryステートメントが正常に完了したか、または突然完了したかに関係なく、リソースを確実に閉じることができます。次の例ではfinallytry-with-resourcesステートメントの代わりにブロックを使用しています。

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

}

ドキュメントを参照してください。


6

最近、Java SE 8プログラマガイドiiの本を読みました。

AutoCloseablevs の違いについて何かを見つけましたCloseable

このAutoCloseableインターフェースはJava 7で導入されました。それ以前は、という別のインターフェースが存在していましたCloseable。これは、次の例外を除いて、言語設計者が望んだものに似ていました。

  • Closeableスローされる例外のタイプをに制限しIOExceptionます。
  • Closeable 実装はべき等である必要があります。

言語設計者は下位互換性を強調しています。既存のインターフェースを変更することは望ましくないため、彼らはと呼ばれる新しいインターフェースを作りましたAutoCloseable。この新しいインターフェースはほど厳密ではありませんCloseable。以来Closeableの要件を満たしている AutoCloseable、それが実装し始めAutoCloseable、後者を導入した場合。


1
「この新しいインターフェースはそれほど厳密ではない」と言う代わりに、「この新しいインターフェースはCloseable、より一般的なコンテキストで使用でき、閉じるときにスローされる例外が必ずしもIOExceptionであるとは限らない」と言うことをお勧めします。Javaの世界では、「それほど厳格ではない」ことは、それについて否定的な雰囲気を持っています。
噴水
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.