Я делаю содержание полученной в наследство системы, и увидел во многих частях один блок, сходный с тем, что он продолжает:
try {
// aqui codigo
} finally {
// mas codigo aqui
}
Мой вопрос: Каковой состоит функция в том, чтобы делать один try .. finally
, без блока catch
?
Контракты - общая концепция в рисунке и анализе исправления алгоритмов. Концепция состоит в том, что функции, методы или другие единицы наших программ должны иметь:
В этой раме, try { ... } finally { ... }
это полезное сооружение для того, чтобы наш код смог гарантировать постусловия даже если встретились исключения внутри блока try { ... }
или в любом методе, призванном внутри этого блока. Ввиду того, что команды внутри блока finally { ... }
всегда они будут работать, исключение или нет, общо помещать там код, который гарантирует постусловия.
Примеры "чистоты", которую другие дали, падают внутри этой рамы. Идея, чем в этих примерах:
Это было использование больше общо finally
в старых версиях Java. В Java 7 ввел новое сооружение, названное "try with resources," который он искажает try { ... } finally { ... }
в Ваших самых общих использованиях:
try (OutputStream out = ...) {
// usar el OutputStream `out`
} // postcondición: `out` ha sido cerrado
Другой класс примера - с программными средствами синхронизации между трэдами ("threads"). В пакете java.util.concurrent.locks
существуют несколько классов замков ("locks"), что обычно используются с try {...} finally {...}
:
Lock l = ...;
l.lock();
try {
// Entre los hilos que comparten la cerradura `l`, sólo uno
// puede entrar en este bloque a la vez.
} finally {
l.unlock();
} // postcondición: la cerradura está abierta
Но нужно нажимать снова концепцию постусловий. В конце концов, try { ... } finally { ... }
это не специально механизм "чистоты" а общего инструмента, чтобы облегчать состав правильных программ. Так что у него есть другие использования, еще, если гораздо менее общие, чем эти два.
Нужно добавлять другой тип примеров. Частая причина ошибок программирования - ранний вывод ("early return") функции или метода. Типичные случаи - нечто похожее:
public LoQueSea miMétodo(Desto algo, Coso queSéYo) {
// muchas lineas...
if (noSéQué()) {
return new LoQueSea(algo); // salida temprana
}
// muchas más lineas...
cosaQueSiempreTieneQuePasar(queSéYo);
return new LoQueSea(algo.con(queSéYo));
}
Предполагая, что всегда нам необходимо называть метод cosaQueSiempreTieneQuePasar()
, у этого примера есть ошибка: когда noSéQué()
возвратись с true
мы выходим ранними и забываем позвонить cosaQueSiempreTieneQuePasar()
. Решение во многих случаях - следующее:
public LoQueSea miMétodo(Desto algo, Coso queSéYo) {
try {
// muchas lineas...
if (noSéQué()) {
return new LoQueSea(algo); // salida temprana
}
// muchas más lineas...
return new LoQueSea(algo.con(queSéYo));
} finally {
// Este bloque se ejecuta siempre, aun si hay
// salida temprana.
cosaQueSiempreTieneQuePasar(queSéYo);
}
}
И здесь удар шаром закрепит, что, несмотря на то, что много ответов упомянули об исключениях как мотив для try {...} finally {...}
, этот пример показывает, что мы можем сталкиваться с проблемами даже, если нет исключений. Другие примеры возможные с break
и continue
в структурах повторения как for (...) {...}
.
Или скорее, исключения, return
рано, break
и continue
они есть что-то общим — ранний вывод блока кода — и finally
это общее решение для проблем, которые вызывают все эти.
Как кажется, это не такая плохая практика, так как finally
всегда он будет работать возможно использовать, чтобы делать чистоту. Я нашел пару примеров в сети:
Пример 1
public void yourMethod() throws YourException {
try {
db.store(mydata);
} finally {
db.cleanup();
}
}
Пример 2
OutputStream os = null;
OutputStreamWriter wos = null;
try {
os = new FileOutputStream(...);
wos = new OutputStreamWriter(os);
// ......
wos.flush();
os.flush();
finally {
IOUtils.closeQuietly(wos);
IOUtils.closeQuietly(os);
}
Здесь пользователь говорит, что в следующем примере catch
он не узнал бы, что делать с ошибкой а следовательно было бы лучше добавлять рутину чистоты.
InputStream in = null;
try {
in = new FileInputStream("file.txt");
// Hacer algo que lance una excepción
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// Nothing we can do.
}
}
}
finally
- liberaci и # 243; n ресурсов со стороны aplicaci и # 243; n.
– Paul Vargas
12.02.2016, 23:48
Блок catch
служи для того, чтобы поймать только какое-то исключение, которое появлялось бы в течение выполнения кода. Так как нет блока catch
, исключение прыгнет и ею будет манипулировать клиент метода, где находился этот блок кода. Если нет никакого управления этого исключения, тогда исключение прыгнет до самого высокого уровня, который сможет достигать. Если самый высокий уровень - метод public static void main(String[] args)
приложения и там он не справляется, тогда приложение покажет исключение, которое бросилось, и "закончится".
Нужно выделять, что блок finally
всегда он работает, состойте в том, чтобы исключение бросилось до самого высокого уровня приложения. Есть случаи, где он не работает finally
но они внешние в этот ответ. Ты можешь видеть их здесь
Используй try-finally
когда твой код не нуждается в том, чтобы манипулировать исключением, потому что уже существует другой уровень, где он справится. Например, в Веб приложении, где у тебя есть какой-то компонент, у X, которые украшают компоненты, которые выполняют просьбы, и X, уже есть способ работать назначенные по умолчанию исключения, которая автоматически они идет в logear, и он покажет "красивое" сообщение пользователю (я не знаю, какое сообщение ошибки красивое в действительности). Пример этого примера (стойте излишек) - случай Спринг MVC, где ты можешь использовать @ControllerAdvice
чтобы манипулировать исключениями на общем уровне. Таким образом, если твой код бросит исключение, ею не будет манипулировать он а класс, украшенный с этой аннотацией.
Это не плохая практика, это тема команды.
Поскольку уже упомянули другие люди, try
с finally
служит для того, чтобы сделать чистоту в случае, что произошла одна excepciГіn, без разбивать эту excepciГіn.
Начиная с Java 7, что у тебя есть try with resources , уже могут существовать даже блоки, которые Гєnicamente включают try
:
try (OutputStream s = getOutputStream()) {
//usar s
}
finally
излишним, потому что stream будет закрываться заканчивая блок.
PodrГ, - чтобы использовать в процессах, которые, если они не удаются, не надо сообщить ему, ни предупреждать пользователя. но это плохая практика, mГ-nimo deberГ, - чтобы записывать log исключений в catch
Полная статья: Try, Catch and Finally. Возможно, что они не использовали блок задержания ошибки, так как не было необходимо реализовывать какой-то тип извещения... Однако, ты был бы должен добавлять это, чтобы, в будущем, идентифицировать лучше почему и, где происходит проблема.
System.out.println("Salgo de la funcion Clase1.pepito()");