Насколько я знаю, интерфейс Closeable был связан с Java 1.5 и AutoCloseable был введен в Java 1.7.
Я пытаюсь понять, почему Closeable extends AutoCloseable, а не наоборот?
Это делается из-за обратной зависимости (неспособности изменить интерфейс Closeable), т.е. Необходимость в AutoCloseable иметь более широкое исключение, чем Closeable? Или моя логика ошибается, и так должно быть?
Почему AutoCloseable базовый интерфейс для Closeable (а не наоборот)?
Ответ 1
Таким образом, весь код пользователя, который реализовал Closeable
, автоматически получает возможность реализовать AutoCloseable
, что позволяет им автоматически извлекать выгоду из синтаксиса try-with-resources.
Ответ 2
Комментарий @Sotirios Delimanolis прибил его.
Команда Java 7 хотела, чтобы механизм маркирования объектов был автоматически закрыт для конструкции "попробуйте с ресурсами". К сожалению, спецификация API для метода Closeable.close()
слишком строгая. Это требует, чтобы метод close()
был идемпотентом... но это не обязательно в случае использования "попробуйте с ресурсами".
Таким образом, они ввели интерфейс AutoClosable
с менее ограничительным семантиком close()
... и ретро-установленным Closeable
в качестве подтипа AutoCloseable
.
Другое дело, что AutoCloseable.close()
объявляется как throw Exception
, а не IOException
. Это означает, что API AutoCloseable
менее ограничительный, чем Closeable
... и учитывая, что он эффективно используется в качестве API обратного вызова в try-with-resources, это делает его более гибким/более широко применимым. (API можно использовать для ресурсов, которые не имеют ничего общего с I/O, но все же могут генерировать исключения при закрытии.) Флип-бок - это то, что Java-типизация не позволит им сделать такое изменение, если метод closes() throws Exception
были введены в подтип.
Альтернативы были бы следующими:
-
чтобы ограничить "попробовать с ресурсами" ресурсам с помощью идемпотентного закрытия... что ограничивает его полезность или
-
чтобы ретроспективно изменить семантику
Closeable.close()
..., что может привести к трудностям для переноса старого кода на Java 7 -
чтобы ретроспективно изменить подпись
Closeable.close()
..., которая нарушила бы двоичную совместимость.
Ответ 3
Интерфейс Closeable
был введен в Java 5.
Когда в Java 7 был введен try-with-resources
(ниже примерный код), разработчики языка хотели изменить некоторые вещи, но нуждались в обратной совместимости (весь код, написанный в предыдущих версиях, не должен устаревать с введением новых функциональных возможностей) поэтому они создали Superinterface AutoCloseable
с правилами, которые они хотели.
Пример попытки с ресурсами:
try (NewResource a = NewResource.CreateResource();
{
}
Над кодом "Попробуйте с ресурсами". Мы просто можем понять, что в этом коде мы можем объявить новую переменную в коде try, и эта переменная может вызвать другие методы в коде. Помимо уменьшения детализации блока try
этот код также не требует блока finally, но исполняющая среда должна быть Java 7 или выше. Хотя, наконец, создается самой JVM.
Closeable
и AutoCloseable
содержит только один метод
void close()
В то время как close ()
метод Closeable
throws IOException
, AutoCloseable
close()
метод выбрасывает Exception
.
Ответ 4
Closeable
имеет некоторые ограничения, поскольку он может только бросать IOException
, поэтому его нельзя изменить без нарушения устаревшего кода.
Итак, был введен AutoCloseable
, который может бросать Exception
.
AutoCloseable
должен использоваться для приложений с помощью > JDK7.
Поскольку библиотеки JDK7 + используют AutoCloseable
, а устаревший код, который реализует Closeable
, по-прежнему должен быть совместим с JDK7 +
это делается для того, чтобы Closeable расширял AutoCloseable.
public interface Closeable extends AutoCloseable {
public void close() throws IOException;
}
AutoCloseable
был специально разработан для работы с операторами try-with-resources.
Поскольку Closeable
extends AutoCloseable
, try-with-resources могут использоваться для закрытия любых ресурсов, которые реализуют либо Closeable, либо AutoCloseable.