2013年5月5日日曜日

[Java]C#のusingのような構文でリソースを開放する(try-with-resources)

時代はJava8に突入しようとしていますが、Java7の話題です。。。
C#のusingは、リソースを開放するのがすごく楽になる構文です。 コード的にはこんな感じ。
class Program
{
    static void Main(string[] args)
    {
        using (Hoge1 hoge1 = new Hoge1())
        {
            hoge1.execute();
        }
    }
}

class Hoge1 : IDisposable
{
    public void execute()
    {
        Console.WriteLine("Hoge1 execute");
    }

    public void Dispose()
    {
        Console.WriteLine("Hoge1 Dispose");
    }
}

Java(6)と比べて非常にすっきりしています。 そのJava6では、こんな感じで非常に残念。
public static void main(String[] args) {
    Hoge1 hoge = null;
    try {
        hoge = new Hoge1();
        hoge.execute();
    } finally {
        if (hoge != null) {
            try {
                hoge.close();
            } catch (IOException e) {
                // ほとんどのケースで、ここで例外が出てもどうしようもない。。。
                // 処理的には割り切りでしょうか。
            }
        }
    }
}

でもJava7のtry-with-resourcesだとこんな感じ。以下の例では、複数のAutoCloseableに対応した場合です。
public static void main(String[] args) {
    try (Hoge2 hoge2 = new Hoge2(); Hoge1 hoge1 = new Hoge1();) {
        hoge1.execute();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

static class Hoge1 implements AutoCloseable {

    public void execute() {
        System.out.println("Hoge1 execute");
    }

    @Override
    public void close() throws IOException {
        System.out.println("Hoge1 close");

        throw new IOException("Hoge1 close");
    }

}

static class Hoge2 implements AutoCloseable {

    public void execute() {
        System.out.println("Hoge2 execute");
    }

    @Override
    public void close() throws IOException {
        System.out.println("Hoge2 close");
    }
}

try構文の特徴も引き継ぐので、ブロック内にcatch文を書くこともできます。
(これ、地味ですが微妙にいい感じ)

C#のusingで複数のIDisposableに対応した書き方をすると、以下の通り。
    using (Hoge1 hoge1 = new Hoge1())
    using (Hoge2 hoge2 = new Hoge2())
    {
        hoge1.execute();
        hoge2.execute();
    }

当時、usingを複数書く構文には違和感を覚えましたが、すっかり慣れてしまいました。あと、import分に対応する文がusingであり、そこも微妙に違和感がありました。
Javaのtry-with-resourcesでは、1つのブロック中に記載するので、逆に違和感が。。。

0 件のコメント: