Подтвердить что ты не робот

Должен ли Closeable использоваться как эквивалент Java для .NET IDisposable?

Обновление. Как показано в @PaulGroke ниже, все изменилось с Java 7: теперь есть AutoCloseable. Который не привязан к потокам и поддерживается новой конструкцией try-with-resources.

AutoCloseable - это прямой эквивалент Java для интерфейса .NET IDisposable.


Интерфейс Closeable, введенный в Java 1.5, тесно связан с потоками и даже имеет спецификатор исключения для IOException. Это говорит о том, что его следует использовать только для потоков или других видов деятельности, связанных с ИО, а не для логики очистки общего назначения.

Конечно, описание метода close() не имело бы никакого смысла вне контекста stream/IO:

void close() throws IOException

Закрывает этот поток и освобождает связанные с ним системные ресурсы.

Должен ли я объявить свой собственный интерфейс Disposable с помощью метода Dispose() на нем и использовать его как аналог интерфейса .NET IDisposable? Или я должен повторно использовать Closeable, хотя это может быть не идеально подходит?

4b9b3361

Ответ 1

Особенно учитывая, что close() выбрасывает IOException, вам нужно написать код обработки исключений, я бы посоветовал вам написать свой собственный интерфейс. Этот интерфейс может затем выкинуть любые проверенные исключения, которые подходят для использования, для которого вы хотите поместить интерфейс.

Интерфейсы имеют тенденцию обозначать намерение в уме читателя, поэтому, имея реализацию класса, связанный с IO интерфейс Closeable заставит читателя предположить, что класс также основан на IO.

Очевидно, что если объекты, которые вы хотите закрыть, связаны с IO, вы должны использовать Closeable. Но в противном случае перейдите к

/** Interface for objects that require cleanup post-use. Call dispose() in finally block! */
public interface Disposable {
    public void dispose();
}

Ответ 2

Я уверен, что большинство людей знают об этом, но поскольку этот вопрос по-прежнему остается одним из лучших результатов при поиске "IDisposable Java" (результат для меня сейчас только 2), и он все еще не упоминается здесь...

Все изменилось с Java 7: теперь есть AutoCloseable. Который не привязан к потокам и поддерживается новой конструкцией try-with-resources.

Ответ 3

При реализации Closeable (или AutoClosable в этом отношении) в классе также можно просто опустить объявление throws:

class X implements Closeable {
    @Override public void close() /* I don't throw */ {

    }
}

Поэтому, когда кто-то использует типизированный объект, он может вызывать close(), не имея возможности поймать что-либо:

void f() { // notice no need for throws because close() doesn't throw
    X x = new X();
    try {
        // do something
    } finally {
        x.close();
    }
}

Он также совместим с любым ожидающим Closeable: если этот объект передается где-то, где обрабатывается Closeable, они уже предвидят исключение и обрабатывают его правильно, хотя и бесполезно в этом случае.

Это включает библиотеки, такие как Guava Closeables и Java 7 try-with-resources, как предлагает Paul Groke:

try (X x = new X()) {
    // do something
}

Там есть редкое предупреждение: вы не можете повторно вводить исключение в дочерних классах после его удаления:

class Y extends X {
                                  /* compile error */
    @Override public void close() throws IOException {
        // Y.close clashes with X.close: overridden method does not throw IOException
    }
}