В Java 7 вам не следует закрывать их явно, а использовать автоматическое управление ресурсами , чтобы гарантировать, что ресурсы закрыты и исключения обрабатываются соответствующим образом. Обработка исключений работает следующим образом:
Exception in try | Exception in close | Result
-----------------+--------------------+----------------------------------------
No | No | Continue normally
No | Yes | Throw the close() exception
Yes | No | Throw the exception from try block
Yes | Yes | Add close() exception to main exception
| | as "suppressed", throw main exception
Надеюсь, это имеет смысл. В позволяет красивый код, как это:
private void doEverythingInOneSillyMethod(String key)
throws MyAppException
{
try (Connection db = ds.getConnection()) {
db.setReadOnly(true);
...
try (PreparedStatement ps = db.prepareStatement(...)) {
ps.setString(1, key);
...
try (ResultSet rs = ps.executeQuery()) {
...
}
}
} catch (SQLException ex) {
throw new MyAppException("Query failed.", ex);
}
}
До Java 7 лучше использовать вложенные блоки finally, а не проверять ссылки на null.
Пример, который я покажу, может показаться уродливым с глубоким вложением, но на практике хорошо спроектированный код, вероятно, не будет создавать соединение, оператор и результаты все в одном методе; часто каждый уровень вложенности включает передачу ресурса другому методу, который использует его как фабрику для другого ресурса. При таком подходе исключения из close()
будут маскировать исключение внутри блока try
. Этого можно преодолеть, но это приводит к еще более грязному коду и требует специального класса исключений, который обеспечивает «подавленную» цепочку исключений, присутствующую в Java 7.
Connection db = ds.getConnection();
try {
PreparedStatement ps = ...;
try {
ResultSet rs = ...
try {
...
}
finally {
rs.close();
}
}
finally {
ps.close();
}
}
finally {
db.close();
}