Какое ключевое требование к ресурсам, используемым в конструкции try-with-resources в Java?

Ответ

Ресурс, объявляемый в try-with-resources, должен реализовывать интерфейс java.lang.AutoCloseable (введен в Java 7) или его более старый подынтерфейс java.io.Closeable.

Почему это требование: Конструкция гарантирует автоматический вызов метода close() для каждого ресурса по завершении блока try, даже в случае возникновения исключения. Наличие интерфейса — это контракт, гарантирующий, что такой метод существует.

Пример корректного использования:

// FileInputStream и BufferedReader реализуют AutoCloseable
try (FileInputStream fis = new FileInputStream("data.bin");
     BufferedReader reader = new BufferedReader(new InputStreamReader(fis))) {
    String line = reader.readLine();
    // работа с ресурсами...
} // Здесь JVM автоматически вызовет reader.close(), затем fis.close()

Важные детали:

  • Ресурсы закрываются в обратном порядке их создания (LIFO).
  • Исключение в блоке try и в методе close() не «гасит» друг друга. Исключение из close() добавляется как suppressed к основному.
  • Попытка использовать не-AutoCloseable ресурс приведет к ошибке компиляции.

Ответ 18+ 🔞

Ну слушай, история такая. Чтобы вот эту штуку, try-with-resources, использовать — твой ресурс должен быть не абы каким, а правильным пацаном. А именно — реализовывать интерфейс java.lang.AutoCloseable (его в седьмую джаву запилили) или его старшего брата java.io.Closeable.

А почему, спрашивается? Да всё просто, как три копейки! Эта конструкция — она как надёжный дворник: когда ты закончил свои дела в блоке try (или накосячил и вылетело исключение), она сама, автоматом, вызовет у каждого ресурса метод close(). А интерфейс — это такая бумажка с печатью, которая гарантирует, что метод close() у объекта вообще есть, иначе какой с него спрос?

Вот смотри, как это выглядит, когда всё по-взрослому:

// FileInputStream и BufferedReader — они оба, блядь, AutoCloseable, пацаны проверенные
try (FileInputStream fis = new FileInputStream("data.bin");
     BufferedReader reader = new BufferedReader(new InputStreamReader(fis))) {
    String line = reader.readLine();
    // делаем тут свои делишки...
} // А тут JVM, тихим сапом, сама вызовет reader.close(), а потом и fis.close(). Красота!

Ещё пара важных фишек, чтобы не облажаться:

  • Ресурсы закрываются в обратном порядке, как таджики на стройке — кто последним пришёл, тот первым идёт мыть полы (LIFO, короче).
  • Если исключение вылетело и в блоке try, и в методе close() — они друг друга не перекричат. То, что из close(), прицепится как suppressed к основному, чтоб не потерялось, хитрая жопа.
  • А если ты попробуешь сунуть в try-with-resources что-то, что не AutoCloseable — компилятор тебе такую ошибку влепит, что мало не покажется. Ошибка компиляции, Карл! Сразу видно — распиздяй.