En caso de que java trate de bloques de alcance tan estrechamente como sea posible?


Me han dicho que hay algo de sobrecarga en el uso del mecanismo Java try-catch. Por lo tanto, si bien es necesario poner métodos que lanzan excepciones verificadas dentro de un bloque try para manejar la posible excepción, es una buena práctica en cuanto al rendimiento limitar el tamaño del bloque try para contener solo aquellas operaciones que podrían lanzar excepciones.

No estoy tan seguro de que esta sea una conclusión sensata.

Considere las dos implementaciones siguientes de una función que procesa una archivo de texto especificado.

Incluso si es cierto que el primero incurre en algunos gastos generales innecesarios, me parece mucho más fácil de seguir. No está tan claro de dónde proceden exactamente las excepciones simplemente por mirar las declaraciones, pero los comentarios muestran claramente qué declaraciones son responsables.

El segundo es mucho más largo y complicado que el primero. En particular, el buen lenguaje de lectura de líneas de la primera tiene que ser modificado para encajar la llamada readLine en un bloque try.

¿Qué es the best practice for handling exceptions in a función where multiple exceptions could be thrown in its definition?

Este contiene todo el código de procesamiento dentro del bloque try:

void processFile(File f)
{
  try
  {
    // construction of FileReader can throw FileNotFoundException
    BufferedReader in = new BufferedReader(new FileReader(f));

    // call of readLine can throw IOException
    String line;
    while ((line = in.readLine()) != null)
    {
      process(line);
    }
  }
  catch (FileNotFoundException ex)
  {
    handle(ex);
  }
  catch (IOException ex)
  {
    handle(ex);
  }
}

Este contiene solo los métodos que arrojan excepciones dentro de los bloques try:

void processFile(File f)
{
  FileReader reader;
  try
  {
    reader = new FileReader(f);
  }
  catch (FileNotFoundException ex)
  {
    handle(ex);
    return;
  }

  BufferedReader in = new BufferedReader(reader);

  String line;
  while (true)
  {
    try
    {
      line = in.readLine();
    }
    catch (IOException ex)
    {
      handle(ex);
      break;
    }

    if (line == null)
    {
      break;
    }

    process(line);
  }
}
Author: Iain Samuel McLean Elder, 2010-04-14

7 answers

La premisa básica aquí es false: el tamaño de un bloque try no hace ninguna diferencia en el rendimiento. El rendimiento se ve afectado por el aumento real de excepciones en tiempo de ejecución, y eso es independiente del tamaño del bloque try.

Sin embargo, mantener los bloques try pequeños puede llevar a mejores programas.

Puede capturar excepciones para recuperar y proceder, o puede capturarlas simplemente para reportarlas al llamante (o a un humano, a través de alguna interfaz de usuario).

En el primer caso, los fallos de los que puede recuperarse a menudo son muy específicos, y esto conduce a bloques try más pequeños.

En el segundo caso, donde una excepción es capturada para que pueda ser envuelta por otra excepción y re-lanzada, o mostrada al usuario, pequeños bloques try significan que usted sabe con más precisión qué operación falló, y el contexto de nivel superior en el que se realizó esa llamada. Esto le permite crear informes de errores más específicos.

Por supuesto, hay exceptions excepciones (¡lo siento!) a estas directrices. Por ejemplo, en algunos casos los informes de errores muy específicos podrían ser un problema de seguridad.


Podría ser útil saber qué efecto tiene un bloque try en el código compilado. ¡No cambia las instrucciones compiladas en absoluto! (Por supuesto, el bloque catch correspondiente lo hace, ya que es como cualquier otro código.)

Un bloque try crea una entrada en la tabla de excepciones asociada con el método. Esta tabla tiene un rango de contadores de instrucciones de origen, una excepción tipo, y una instrucción de destino. Cuando se genera una excepción, se examina esta tabla para ver si hay una entrada con un tipo coincidente y un rango que incluye la instrucción que genera la excepción. Si lo hace, la ejecución se ramifica al número de destino correspondiente.

Lo importante a tener en cuenta es que esta tabla no se consulta (y no tiene ningún efecto en el rendimiento de ejecución) a menos que sea necesario. (Descuidando un poco de sobrecarga en la carga de la clase.)

 45
Author: erickson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-13 23:52:00

Me han dicho que hay algo de sobrecarga en el uso del mecanismo Java try-catch.

Absolutamente. Y también hay sobrecarga para las llamadas de método. Pero no deberías poner todo tu código en un solo método.

No toot el cuerno de optimización prematura, pero el enfoque debe estar en la facilidad de lectura, organización, etc. Las construcciones de lenguaje rara vez afectan el rendimiento tanto como la organización del sistema y la elección de algoritmos.

Para mí, el primero es más fácil de leer.

 11
Author: Jonathon Faust,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-13 23:27:40

No. Lo único que debe considerar es dónde puede manejar razonablemente la excepción y qué recursos necesita para reclamar (finalmente).

 3
Author: CurtainDog,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-13 23:58:37

Esta es una optimización prematura en su peor momento. No lo hagas.

"Deberíamos olvidarnos de las pequeñas eficiencias, digamos alrededor del 97% de las veces: la optimización prematura es la raíz de todo mal" - Knuth.

 2
Author: luis.espinal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-14 03:01:35

Hay muy muy poco beneficio para el 2do método. después de todo, si puede abrir un archivo con éxito, pero no leer de él, entonces hay algo muy mal con su computadora. por lo tanto, saber que la excepción io vino del método readLine() es muy rara vez útil. también como usted sabe, se lanzan diferentes excepciones para diferentes problemas de todos modos (FileNotFoundException, etc.)

Siempre y cuando lo alcance con un bloque 'lógico', es decir, abrir, leer y cerrar un archivo en 1 go, lo haría vaya con el primer método. es mucho más simple de leer y, especialmente cuando se trata de IO, los ciclos del procesador utilizados por la sobrecarga de prueba-captura serían mínimos si los hubiera.

 1
Author: oedo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-13 23:20:47

Poner los bloques de prueba alrededor del código específico que puede lanzar una excepción, lo hace, en mi opinión, más fácil de leer. Es probable que desee mostrar un mensaje diferente para cada error y proporcionar instrucciones al usuario, que serán diferentes dependiendo de dónde se produzca el error.

Sin embargo, el problema de rendimiento al que se refiere la mayoría de las personas está relacionado con el aumento de la excepción, no con el bloque try en sí.

En otras palabras, siempre y cuando usted nunca tiene un error planteado, la intentar bloquear no afectará notablemente el rendimiento. No debe considerar un bloque de prueba solo otra construcción de control de flujo y generar un error para ramificar a través de su código. Eso es lo que quieres evitar.

 1
Author: Marcus Adams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-14 14:13:58

El segundo método generará un error del compilador que reader puede no haber sido inicializado. Puede evitar eso inicializándolo a null, pero eso solo significa que podría obtener un NPE, y no hay ninguna ventaja en eso.

 0
Author: Matt McHenry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-13 23:23:18