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

Как в Java обеспечивается идемпотентность метода close() интерфейса Closeable?

Интерфейс Closeable был введен в Java 5, тогда как интерфейс AutoCloseable появился в Java 7 вместе с оператором try-with-resources. Closeable расширяет (начиная с Java 7) интерфейс AutoCloseable.

В книге OCA/OCP Java SE 7 - Учебное пособие для программистов я и II говорится на стр. 399:

Что происходит, если мы назовем close() несколько раз? Это зависит. Для классов, реализующих AutoCloseable, реализация должна быть идемпотентной. Это означает, что вы можете называть close() весь день, и ничего не произойдет во второй раз и за его пределами. [...] Для классов, реализующих Closeable, такой гарантии нет.

Поэтому в соответствии с этим текстом реализации AutoCloseable должны быть идемпотентными, а те, что указаны в Closeable, нет. Теперь, когда я смотрю документацию AutoCloseable на docs.oracle.com, он говорит:

Обратите внимание, что в отличие от метода close Closeable этот закрытый метод не должен быть идемпотентным. Другими словами, вызов этого метода close более одного раза может иметь некоторый видимый побочный эффект, в отличие от Closeable.close, который не должен иметь эффекта, если вызывается более одного раза.

Теперь это противоположность тому, что написано в книге. У меня есть два вопроса:

(1) Что правильно? Док на docs.oracle.com или в книге? Какой из двух интерфейсов требует идемпотенции?

(2) Независимо от того, какой из них должен быть идемпотентным, я прав, что Java фактически не имеет никакого способа гарантировать, что он идемпотент? Если это так, "требование" метода close быть идемпотентным является тем, что программист должен, но я никогда не могу быть уверен, что тот, кто использовал интерфейс, действительно сделал это, правильно? В этом случае идемпотентность - это просто предложение оракула, правильно?

4b9b3361

Ответ 1

  • Javadoc из Oracle верен. Просто интуиция, почему - AutoCloseable объекты используются в блоках try(){}, где close фактически вызывается автоматически и только один раз; в то же время close() из метода интерфейса Closeable вы всегда вызываете вручную, и вы можете вызвать его дважды случайно или сделать код более удобным для чтения. Кроме того, Closeable расширяет AutoCloseable и не может уменьшить контракт метода close() от AutoCloseable - он может только добавлять требования. Итак, абстрактная ситуация, когда AutoCloseable требуется close(), чтобы быть идемпотентным, а расширенный интерфейс отменил это требование, было бы просто плохим дизайном.

  • Да, ваше понимание правильно. Это просто контракт, который должен учитывать программист. Как и контракт между equals() и hashCode(). Вы можете реализовать его непоследовательно, и никто не скажет вам. Вероятно, у вас будут проблемы во время выполнения.