(Late edición:. Esta pregunta se espera que sea obsoleta cuando Java 7 viene, debido a la "final rethrow" feature cuales seems like it will be added)¿Cuán seguro es mi regreso seguro?
Muy a menudo, me encuentro en situaciones que parecen esto:
do some initialization try { do some work } catch any exception { undo initialization rethrow exception }
En C# puede hacerlo de esta manera:
InitializeStuff();
try
{
DoSomeWork();
}
catch
{
UndoInitialize();
throw;
}
Para Java, no hay una buena sustitución, y desde the proposal for improved exception handling was cut from Java 7, parece que tomará, en el mejor de los casos, varios años hasta que obtengamos algo así. Por lo tanto, decidí rodar mi propia:
(Editar:. Medio año después, final rethrow is back, o eso parece)
public final class Rethrow {
private Rethrow() { throw new AssertionError("uninstantiable"); }
/** Rethrows t if it is an unchecked exception. */
public static void unchecked(Throwable t) {
if (t instanceof Error)
throw (Error) t;
if (t instanceof RuntimeException)
throw (RuntimeException) t;
}
/** Rethrows t if it is an unchecked exception or an instance of E. */
public static <E extends Exception> void instanceOrUnchecked(
Class<E> exceptionClass, Throwable t) throws E, Error,
RuntimeException {
Rethrow.unchecked(t);
if (exceptionClass.isInstance(t))
throw exceptionClass.cast(t);
}
}
uso típico:
public void doStuff() throws SomeException {
initializeStuff();
try {
doSomeWork();
} catch (Throwable t) {
undoInitialize();
Rethrow.instanceOrUnchecked(SomeException.class, t);
// We shouldn't get past the above line as only unchecked or
// SomeException exceptions are thrown in the try block, but
// we don't want to risk swallowing an error, so:
throw new SomeException("Unexpected exception", t);
}
private void doSomeWork() throws SomeException { ... }
}
Es una Un poco prolijo, capturar Throwable
es generalmente mal visto, no estoy muy contento de usar la reflexión solo para volver a lanzar una excepción, y siempre me siento un poco incómodo escribiendo comentarios de "esto no sucederá", pero en la práctica funciona w ell (o parece, al menos). Lo que me pregunto es:
- ¿Tengo algún defecto en mis métodos de ayuda al rebrote? ¿Algunos casos de esquina que me he perdido? (Sé que el
Throwable
puede haber sido causado por algo tan severa que miundoInitialize
se producirá un error, pero está bien.)- Alguien ya ha inventado esto? Miré a Commons Lang
ExceptionUtils
pero eso hace otras cosas.
- Alguien ya ha inventado esto? Miré a Commons Lang
Editar:
finally
no es el androide que estoy buscando. Solo me interesa hacer cosas cuando se lanza una excepción.- sí, ya sé captura
Throwable
es un gran no-no, pero yo creo que es el mal menor en comparación con tener aquí tres cláusulas de captura (porError
,RuntimeException
ySomeException
, respectivamente) con el mismo código. - Tenga en cuenta que no estoy tratando de suprimir ningún error, la idea es que cualquier excepción lanzada en el bloque
try
continuará surgiendo a través de la pila de llamadas tan pronto como haya relanzado algunas cosas.
Tiene una buena razón para atrapar a Throwable. No dejes que te deprima. Es muy parecido al uso de GOTO, "Nunca lo uses, a menos que sea necesario". –