Definitivamente puedo pensar en situaciones en las que preferiría preferir la excepción de ser una clase interna estática que simplemente una clase en el mismo paquete.
Las razones para no hacerlo parecen ser:
- El acoplamiento de la excepción a la clase que lo tira hace inadecuado para reutilizar en otros contextos
- nadie más lo hace es
No creo que ninguno de esos argumentos sea convincente.
Para el primer punto, ¿por qué debería surgir esta hipotética oportunidad futura de reutilización en el mismo paquete? Este argumento lleva a la conclusión de que debemos colocar todas las clases de excepciones lo más alto posible en la jerarquía de paquetes para que cuando descubramos una oportunidad futura de reutilizar la misma excepción no tengamos que introducir una dependencia en donde se definió originalmente.
Pero incluso sin el punto "llevado a extremos", considere una excepción destinada a comunicar que la clase Foo
recibió una entrada incorrecta. Si lo llamo Foo.InvalidInput
, el nombre es corto y la asociación con Foo
es imposible de perder. Si lo coloco fuera de la clase Foo
y lo llamo FooInvalidCriteria
, entonces no puedo reutilizarlo de la clase Bar
de todos modos, sin cambiar su nombre (equivalente a cambiar su ubicación).
Pero lo peor es si lo dejo fuera Foo
y mantengo su nombre general como InvalidInput
. Luego, cuando más tarde me doy cuenta de que Bar
también podría tener una entrada no válida y hacer que comience a arrojar esta excepción. Todo compila y funciona bien, solo que ahora todos los lugares que estaban capturando InvalidInput
y asumiendo que estaban manejando errores de Foo
ahora podrían estar manejando errores de Bar
si Foo
usa internamente el Bar
de una manera que podría causar esta excepción. Esto podría causar la rotura del código fácilmente.
La realidad es que la adopción de una excepción que anteriormente se concibe como específicamente lo que indica una situación que se presente en una clase y re-usando como una clase de error general es un cambio en la interfaz , no sólo un cambio de implementación interna. Para hacerlo correctamente, en general, debe volver a visitar todos los sitios donde se captura la excepción y asegurarse de que siguen siendo correctos, por lo que el compilador le informará sobre todos los sitios de uso (porque debe cambiar el nombre y/o ruta de importación) es una buena cosa. Cualquier excepción que podría hacer crear una clase interna estática no es apropiada para su reutilización en otros contextos, sin importar si realmente la convierte en una clase interna o no.
Y en cuanto al segundo punto de punto ... "nadie más lo hace" nunca se sostiene en nada. O bien, realmente es lo incorrecto, por lo que habrá otras razones para no hacerlo, por lo que el argumento de "nadie más lo hace" es innecesario. O no lo es. Y no es que este ejemplo en particular sea terriblemente complicado y difícil de entender, por lo que ni siquiera el argumento "es inesperado para que la gente tenga problemas para seguirlo aunque sea una buena idea en teoría" es muy fuerte.
La misma pregunta y las mismas opciones se podrían aplicar a cualquier clase. ¿Hay alguna característica de excepciones que los haga especialmente adecuados para la anidación, o simplemente pregunta [cuándo utilizar clases anidadas?] (Https://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html) – jaco0646