Попробуйте с ресурсами против Try-Catch

Я искал код, и я видел попытку с ресурсами. Раньше я использовал стандартную инструкцию try-catch, и похоже, что они делают то же самое. Поэтому мой вопрос: " Попробуйте с ресурсами против Try-Catch", каковы различия между ними, и что лучше.

Вот попытка с ресурсами:

objects jar = new objects("brand");
objects can= new objects("brand");

try (FileOutputStream outStream = new FileOutputStream("people.bin")){
    ObjectOutputStream stream = new ObjectOutputStream(outStream);

    stream.writeObject(jar);
    stream.writeObject(can);

    stream.close();
} catch(FileNotFoundException e) {
    System.out.println("sorry it didn't work out");
} catch(IOException f) {
    System.out.println("sorry it didn't work out");
}

Ответы

Ответ 1

Основная задача try-with-resources - убедиться, что ресурсы надежно закрыты.

Когда вы не используете try-with-resources, существует потенциальная ловушка, называемая маскированием исключений. Когда код в блоке try выдает исключение, а метод close в finally также генерирует исключение, исключение, выбрасываемое блоком try, теряется, а исключение, выданное в блоке finally, распространяется. Это обычно неудачно, так как исключение, выдаваемое при закрытии, является чем-то бесполезным, а полезное исключение является информативным. (Таким образом, вместо того, чтобы видеть исключение SQLException, которое сообщает вам, какое ограничение RI было нарушено, вы видите что-то вроде BrokenPipeException, когда закрытие ресурса перекрывается.)

Такая маскировка исключений является досадной проблемой, которая предотвращает попытка использования ресурсов.

Чтобы гарантировать, что маскирование исключений не потеряет важную информацию об исключениях, при разработке try-with-resources они должны были решить, что делать с исключениями, генерируемыми методом close.

При использовании try-with-resources, если блок try генерирует исключение, а метод close также генерирует исключение, то исключение из блока close прикрепляется к исходному исключению:

... бывают ситуации, когда два независимых исключения могут быть сгенерированы в соседних блоках кода, в частности, в блоке try оператора try-with-resources и сгенерированном компилятором блоке finally, который закрывает ресурс. В этих ситуациях может распространяться только одно из сгенерированных исключений. В инструкции try-with-resources, когда есть два таких исключения, исключение, происходящее из блока try, распространяется, и исключение из блока finally добавляется в список исключений, подавленных исключением из блока try. Поскольку исключение раскручивает стек, оно может накапливать несколько исключенных исключений.

С другой стороны, если ваш код завершается нормально, но ресурс, который вы используете, генерирует исключение при закрытии, это исключение (которое будет подавлено, если код в блоке try выдаст что-нибудь), будет выдано. Это означает, что если у вас есть некоторый код JDBC, в котором ResultSet или PreparedStatement закрывается попыткой с ресурсами, может возникнуть исключение, возникающее из-за некоторого сбоя инфраструктуры при закрытии объекта JDBC, и может откатить операцию, которая в противном случае была бы успешно завершена,

Без try-with-resources создается ли исключение метода close - зависит от кода приложения. Если он генерируется в блоке finally, когда блок try генерирует исключение, исключение из блока finally скрывает другое исключение. Но у разработчика есть возможность отловить исключение, выброшенное при закрытии, и не распространять его.

Ответ 2

Вы что-то пропустили, finally блок. try-with-resouces сделает что-то вроде,

FileOutputStream outStream = null;
try {
  outStream = new FileOutputStream("people.bin");
  ObjectOutputStream stream = new ObjectOutputStream(outStream);

  stream.writeObject(jar);
  stream.writeObject(can);

  stream.close();
} catch(FileNotFoundException e) {
    System.out.println("sorry it didn't work out");
} catch(IOException f) {
    System.out.println("sorry it didn't work out");
} finally {
  if (outStream != null) { 
    try { 
      outStream.close(); 
    } catch (Exception e) {
    } 
  }
}

Это означает, что вы действительно хотели что-то вроде (никогда не проглатывайте исключения),

try (FileOutputStream outStream = new FileOutputStream("people.bin");
     ObjectOutputStream stream = new ObjectOutputStream(outStream);) {
  stream.writeObject(jar);
  stream.writeObject(can);
  // stream.close(); // <-- closed by try-with-resources.
} catch(FileNotFoundException e) {
    System.out.println("sorry it didn't work out");
    e.printStackTrace();
} catch(IOException f) {
    System.out.println("sorry it didn't work out");
    e.printStackTrace();
}

Ответ 3

Единственное различие заключается в том, что try-resource автоматически добавляет resource.close(); как вы делали бы в finally block

Ответ 4

Любой объект (либо класс, либо их суперкласс), который реализует java.lang.AutoCloseable или java.io.Closeable может использоваться только в предложении try-with-resource. Интерфейс AutoClosable является родительским интерфейсом, а Closable-интерфейс расширяет интерфейс AutoClosable. Интерфейс закрытого доступа имеет закрытый метод, который генерирует исключение, а Closable-интерфейс имеет метод, который генерирует IOException. У нас также может быть улов и, наконец, блок, за которым следует try-with-resource, как обычная попытка, catch и, наконец, но catch и, наконец, блокировка только запускаются после того, как ресурс, объявленный внутри предложения try-with-resource, закрыт.