¿Los bloques de java try deben tener el scope lo más ajustado posible?

Me han dicho que hay una sobrecarga en el uso del mecanismo de prueba de Java. Entonces, si bien es necesario poner métodos que arrojen una excepción comprobada dentro de un bloque try para manejar la posible excepción, es una buena práctica para el rendimiento limitar el tamaño del bloque try para que contenga solo aquellas operaciones que podrían generar excepciones.

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

Considere las dos implementaciones a continuación de una función que procesa un archivo de texto especificado.

Incluso si es cierto que el primero incurre en una sobrecarga innecesaria, me resulta mucho más fácil de seguir. Está menos claro de dónde provienen exactamente las excepciones al solo 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, la buena expresión de lectura de línea del primero tiene que ser mutilada para ajustar la llamada de readLine a un bloque de prueba.

¿Cuál es la mejor práctica para manejar excepciones en una función donde se pueden lanzar múltiples excepciones en su definición?

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); } } 

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

Sin embargo, mantener los bloques de prueba pequeños puede conducir a mejores progtwigs.

Puede atrapar excepciones para recuperar y continuar, o puede atraparlas simplemente para informarlas a la persona que llama (o a un ser humano, a través de alguna IU).

En el primer caso, las fallas de las cuales puede recuperarse son a menudo muy específicas, y esto lleva a bloques de try más pequeños.

En el segundo caso, donde se captura una excepción para que pueda ser envuelta por otra excepción y se vuelva a lanzar, o se muestre al usuario, los bloques de try pequeños significan que usted sabe con más precisión qué operación falló, y el contexto de nivel superior en que esa llamada fue hecha. Esto le permite crear informes de error más específicos.

Por supuesto, hay … excepciones (¡lo siento!) A estas pautas. Por ejemplo, en algunos casos, informes de error muy específicos podrían ser un problema de seguridad.


Puede ser útil saber qué efecto tiene un bloque try en el código comstackdo. ¡No cambia las instrucciones comstackdas 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, un tipo de excepción y una instrucción de destino. Cuando se presenta una excepción, esta tabla se examina para ver si hay una entrada con un tipo coincidente y un rango que incluye la instrucción que generó la excepción. Si lo hace, la ejecución se bifurca al número de destino correspondiente.

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

Me han dicho que hay una sobrecarga en el uso del mecanismo de prueba de Java.

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

No para tocar la bocina de optimización prematura, pero la atención debe centrarse 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 el más fácil de leer.

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

Esta es una optimización prematura en el peor de los casos. No lo hagas

“Deberíamos olvidarnos de pequeñas eficiencias, digamos aproximadamente el 97% del tiempo: la optimización prematura es la raíz de todo mal” – Knuth.

hay muy, muy poco beneficio para el segundo método. después de todo, si puede abrir con éxito un archivo pero no leerlo, entonces hay algo muy incorrecto en su computadora. sabiendo que la excepción io provenía del método readLine () raramente es útil. también como usted sabe, diferentes excepciones se arrojan para diferentes problemas de todos modos (FileNotFoundException, etc.)

siempre y cuando lo scope con un bloque “lógico”, es decir, abrir, leer y cerrar un archivo en 1 go, iría 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 tara de try-catch serían mínimos, si los hubiera.

Poner los bloques de prueba alrededor del código específico que puede arrojar 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á diferente dependiendo de dónde se produce el error.

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

En otras palabras, siempre que nunca se presente un error, el bloque de prueba no afectará de forma notable el rendimiento. No deberías considerar un locking try solo otro constructo de control de flujo y generar un error para ramificar tu código. Eso es lo que quieres evitar.

El segundo método generará un error de comstackción que puede que el reader no se haya inicializado. Puede solucionarlo inicializándolo como null , pero eso solo significa que puede obtener un NPE, y eso no tiene ninguna ventaja.