2009-10-29 12 views
5

En mi código de Java, tengo una función llamada getAngle() que a veces arroja un NoAngleException. ¿Es el siguiente código la mejor manera de escribir una función que sigue llamando al getAngle() hasta que no se arroje ninguna excepción?En Java, ¿cuál es la mejor manera de seguir llamando a una función hasta que no se produzca ninguna excepción?

public int getAngleBlocking() 
{ 
    while(true) 
    { 
     int angle; 
     try 
     { 
      angle = getAngle(); 
      return angle; 
     } 
     catch(NoAngleException e) 
     { 

     } 
    } 
} 

o sería una mejor idea de reescribir getAngle() para volver NaN en el error?

Respuesta

8

Me sorprende leer algunas de las respuestas a este tema ya que este escenario es precisamente la razón comprueba existen excepciones. Podría hacer algo como:

private final static int MAX_RETRY_COUNT = 5; 

//... 

int retryCount = 0; 
int angle = -1; 

while(true) 
{ 
    try 
    { 
     angle = getAngle(); 
     break; 
    } 
    catch(NoAngleException e) 
    { 
     if(retryCount > MAX_RETRY_COUNT) 
     { 
      throw new RuntimeException("Could not execute getAngle().", e); 
     } 

     // log error, warning, etc. 

     retryCount++; 
     continue; 
    } 
} 

// now you have a valid angle 

Esto supone que algo fuera del proceso cambió mientras tanto. Por lo general, algo así como esto se haría para volver a conectar: ​​

private final static int MAX_RETRY_COUNT = 5; 

//... 

int retryCount = 0; 
Object connection = null; 

while(true) 
{ 
    try 
    { 
     connection = getConnection(); 
     break; 
    } 
    catch(ConnectionException e) 
    { 
     if(retryCount > MAX_RETRY_COUNT) 
     { 
      throw new RuntimeException("Could not execute getConnection().", e); 
     } 

     try 
     { 
      TimeUnit.SECONDS.sleep(15); 
     } 
     catch (InterruptedException ie) 
     { 
      Thread.currentThread().interrupt(); 
      // handle appropriately 
     } 

     // log error, warning, etc. 

     retryCount++; 
     continue; 
    } 
} 

// now you have a valid connection 
5

Creo que deberías investigar por qué getAngle() arroja una excepción y luego resuelve el problema. Si esto es aleatorio, como la entrada de un sensor, tal vez deberías esperar un tiempo hasta volver a llamar. También puedes hacer el bloqueo getAngle(), lo que significa que getAngle() esperará hasta que se obtenga un buen resultado.

Ignorando cómo está resolviendo su problema, debe tener algún tipo de mecanismo de tiempo de espera, para que no termine en un ciclo infinito. Esto supone que no desea tener un bucle posiblemente infinito, por supuesto.

+0

Acepto - getAngleBlocking() simplemente enmascara cualquier problema subyacente, causando potencialmente sus propios problemas causando un ciclo infinito o cuello de botella de rendimiento. – Adamski

+0

Por supuesto, debe haber tiempos de espera para bloquear llamadas. He eliminado esa observación para mantenerlo simple. – ziggystar

+0

El objetivo de getAngleBlocking es proporcionar una versión de bloqueo de getAngle. Si decido hacer el bloqueo de getAngle, eso derrota el punto del ejercicio. – Eric

3

¿Desea llamar a un método siempre que arroje una excepción?

Esto no es programación. Deberías usar el depurador y echar un vistazo al verdadero problema.

¡Y nunca debe detectar una excepción sin ningún mensaje o registro!

+0

Intencionalmente hago que arroje la excepción. Estoy esperando la excepción. 'getAngle()' intenta convertir una dirección entre 1 y 9 en un ángulo en grados. Sin embargo, la dirección es a veces 0, que no corresponde a un ángulo. – Eric

1

No recomendaría hacerlo de esa manera, porque cuando getAngle() nunca devuelve un valor válido (siempre arroja una excepción por algún motivo) termina en un bucle infinito. Al menos debe definir una condición de interrupción (por ejemplo, tiempo de espera) para este caso.

+0

Buen punto. Agregaré un tiempo de espera. – Eric

0

Nunca utilice excepciones para manejar la lógica en su código.

como se sugiere primer cheque por eso que a veces encuentras la execption

0

A menos que utilice una clase que está totalmente fuera de su control, que realmente desee volver a examinar una excepción para indicar ningún ángulo.

A veces, por supuesto, esto tampoco es posible porque la clase no es suya, o no es posible hacer doble uso del tipo devuelto como resultado o estado de error.

Por ejemplo, en su caso, suponiendo que todos los grados enteros (negativos y 0) son ángulos posibles, no hay forma de que devuelva un valor int que indique error y sea distinto de un valor de ángulo válido.

Pero supongamos que sus ángulos válidos están en el rango -360 -> 360 (o equivalentes en radianes). Entonces, usted realmente debe considerar algo como:

// assuming this .. 
public static final int NO_ANGLE_ERROR = Integer.MIN_VALUE; 

// do this 
public int getAngleBlocking() 
{ 
    int angle; 
    do { 
     angle = getAngle(); 
    }while(angle == NO_ANGLE_ERROR); 
} 
+0

Esa fue mi manera original de hacerlo. Sin embargo, las excepciones parecían una mejor manera de hacerlo, ya que evitaba usos descuidados de 'getAngle()' donde el caso excepcional no se verificaba. – Eric

1

Al final he optado por devolver un valor NaN, ya que esto evita el uso descuidado de Integer.MIN_VALUE en otro lugar.

public float getAngle(boolean blocking) 
{ 
    while(true) 
    { 
     int dir = getDirection(); 
     if(dir == 0 && !blocking) 
      return Float.NaN; 
     else 
      return (dir - 5) * 30; 
    } 
} 
3

¿No podría haber utilizado recursión? es decir;

public int getAngleBlocking() 
{ 
     int angle; 
     try 
     { 
       angle = getAngle(); 
       return angle; 
     } 
     catch(NoAngleException e) 
     { 
       return getAngleBlocking(); 
     } 
    } 
} 
+0

Y sí, me doy cuenta de que esto es terriblemente malo en las circunstancias equivocadas. Supongo que la excepción NoAngleException es una excepción aleatoria causada por un sensor o algo así. – Amoeba

Cuestiones relacionadas