2010-02-04 8 views
17

Tengo una función que realiza un bucle mientras se hace algo que podría arrojar una excepción. Se parece a esto:Lanzar una lista vinculada de excepciones en Java

public void myFunction() throws MyException { 
    while(stuff) { 
     try { 
      DoSomething() // throws an exception 
     } 
     catch (Exception ex) { 
      throw new MyException(some, stuff, of, mine, ex); 
     } 
    } 
} 

El error que causa la excepción es recuperable. Puede ser algo así como un error de SQL en una única declaración de actualización donde el ciclo while ejecuta una serie de instrucciones de actualización. O un error de análisis en una sola pieza de datos, donde el ciclo procesa múltiples piezas de datos. Necesito pasar la excepción más arriba de la cadena para que la parte de la GUI del programa pueda procesarla, manejarla y transmitir el error al usuario. Pero no quiero matar el bucle en esta función en particular. Las otras cosas que está haciendo podrían no ser inválidas. El error que causó la excepción podría no ser fatal para la función.

Así que mi pregunta es la siguiente: ¿Es una práctica aceptable construir listas vinculadas de excepciones personalizadas (donde cada excepción es un nodo y la excepción arroja el encabezado de la lista) y luego arrojar el encabezado de la lista (en su caso) una vez que termina el ciclo?

¿Alguien ha visto esto hecho? ¿Alguien puede pensar en algún problema potencial al hacer esto? ¿Puede alguien pensar en otras formas mejores de manejar el problema raíz: la necesidad de pasar múltiples excepciones no relacionadas sin salir de la función hasta que se complete?

Aquí hay un ejemplo de cómo la vinculación y un tiro podrían ser implementadas de manera muy sencilla:

public void myFunction() throws MyException { 
    MyException head = null; 
    while(stuff) { 
     try { 
      DoSomething() // throws an exception 
     } 
     catch (Exception ex) { 
      MyException tmp = new MyException(some, stuff, of, mine, ex); 
      tmp.next(head); 
      head = tmp; 
     } 
    } 
    if(head != null) 
     throw head; 
} 
+2

Por cierto. Más allá usas una lista vinculada aquí o no. Hay una clase 'java.util.LinkedList' lista para usar, por lo que no tiene que programar su funcionamiento dentro de los objetos de su artículo (en este caso,' MyException'). – helios

+0

Soy consciente de ello. No pensé que podrías usarlo en este caso, porque la lista debe ser lanzada y LinkedList no es un tema desechable. –

Respuesta

16

Mi pensamiento intial (aparte de que no he visto esto) es que una excepción es potencialmente bastante un objeto grande (que contiene stacktrace) y prefiero no para almacenar muchos de ellos.

En su lugar, crearía una lista de los parámetros/argumentos erróneos a medida que ocurren las excepciones y una vez completado el ciclo, ejecute una excepción personalizada con esta lista (si la lista tiene más de 0 elementos). Esa sería una forma más manejable de manejar este escenario.

public void myFunction() throws CustomException { 
    List<MyError> errors = new ArrayList<MyError>(); 
    while(stuff) { 
     try { 
      DoSomething() // throws an exception 
     } 
     catch (Exception ex) { 
      errors.add(new MyError(some, stuff, of, mine, ex)); 
     } 
    } 
    if (errors.size() > 0) { 
     throw new CustomException(errors); 
    } 
} 
+0

La firma de función existente devuelve vacío. Simplemente podría devolver la lista de objetos fallidos, o alguna otra estructura que recolecta el éxito y el fracaso, etc. – TREE

+0

@TREE Estoy bastante seguro de que es un ejemplo, no es el método real – Kevin

+0

+1, es más nítido que el mío. Arreglé tu código para declarar 'throws CustomException'. Oh, ten en cuenta que 'Error' es una clase existente en' java.lang'. Tal vez te gustaría cambiar el nombre para evitar confusiones. – BalusC

3

¿Realmente necesita tirar todas las excepciones? ¿Cómo espera que se manejen las excepciones individuales no relacionadas? En general, en casos como este, el sistema simplemente informará los errores y terminará.

Si es así, es posible que desee recopilar los mensajes de error y agregarlos a una clase personalizada Exception y lanzar eso.

1

Si la excepción lanzada por DoSomething(); podría causar el mismo método lanzar otra excepción; esto podria ser un problema. En otras palabras, si DoSomething(); arroja una excepción porque no manejó el anterior, puede haber un error innecesario de manejar.

+0

Verdadero. En el escenario que estoy preguntando acerca de esto no sería (teóricamente) el caso, sin embargo, esto es definitivamente algo a tener en cuenta. –

3

Si esas excepciones no están realmente relacionadas entre sí, por lo que no puede beneficiarse de get/setCause(), entonces preferiría recopilar esta información en un MyException.

E.g.

public void myFunction() throws MyException { 
    MyException myException = null; 
    while(stuff) { 
     try { 
      DoSomething() // throws an exception 
     } 
     catch (Exception ex) { 
      if (myException == null) { 
       myException = new MyException(); 
      } 
      myException.addException(some, stuff, of, mine, ex); 
     } 
    } 
    if (myException != null) { 
     throw myException; 
    } 
} 

Actualización:Brian maneja exactamente este enfoque de una manera más ordenada.Optaría por eso en su lugar :)

0

IMO, una excepción debería ser el último recurso que tiene para manejar un error. Debería evitarse si es posible. Por lo tanto, es posible que desee pasar la descripción del error (crear códigos de error, pasar el mensaje o algo significativo) a la GUI, y no la excepción en sí misma.

2

En realidad, arrojar cualquier excepción de dicha función probablemente no sea la forma correcta de manejar esto si se espera que haya errores. Sugeriría devolver una Lista (Array) de todas las excepciones/errores que ocurrieron o mejor para proporcionar un objeto controlador de errores a la función que pueda manejar las excepciones. es decir:

public interface ErrorHandler 
{ 
    public void handleError(Throwable ex /*, add some context info */); 
} 

public void myFunction(ErrorHandler eh) 
{ 
    while(stuff) { 
     try { 
      DoSomething() // throws an exception 
     } 
     catch (Exception ex) { 
      if(eh != null) 
       eh.handleError(ex); 
     } 
    } 
} 

Esto también permite que el controlador de errores o bien recoger los errores de presentarlos al usuario o al decidir que toda la operación por lotes se ha convertido en vacío debido a algún error y para lanzar una excepción de su propia para abortar el procesamiento temprano.

+0

Veo que este enfoque es mejor que la respuesta de @Brain Agnew por las siguientes razones 1. El controlador de errores le permite manejar diferentes excepciones de forma diferente si es necesario 2. Ya no creará una matriz de errores (o algún tipo de indicadores) que esté manejando errores a medida que ocurren – Stackee007

1

Creo que puede pasar alguna devolución de llamada u oyente del método, o establecer una variable de clase y en lugar de arrojar la lista, como lo hizo x4u.

En Java no es una interfaz para esto ya: java.beans.ExceptionListener

Cuestiones relacionadas