tipos propagacion programacion marcadas manejo excepciones errores ejemplos java exception checked-exceptions

propagacion - tipos de excepciones en java



Cuándo elegir las excepciones marcadas y no marcadas (17)

La regla que uso es: ¡nunca use excepciones sin marcar! (o cuando no ves ninguna forma de evitarlo)

Hay un caso muy fuerte de lo contrario: nunca use excepciones marcadas. Soy reacio a tomar partido en el debate, pero parece haber un amplio consenso en que la introducción de excepciones marcadas fue una decisión equivocada en retrospectiva. Por favor, no disparen al messenger y refiéranse a those arguments .

En Java (o en cualquier otro idioma con excepciones comprobadas), al crear su propia clase de excepción, ¿cómo decide si debe marcarse o desmarcarse?

Mi instinto es decir que se requeriría una excepción marcada en los casos en que la persona que llama podría recuperarse de alguna manera productiva, mientras que una excepción sin marcar sería más para casos irrecuperables, pero me interesarían los pensamientos de los demás.


Aquí está mi ''regla general''.
Yo suelo:

  • excepción sin marcar dentro del código de mi método para una falla debida a la persona que llama (que involucra una documentación explícita y completa )
  • excepción marcada por un error debido al callee que tengo que hacer explícita a cualquiera que quiera usar mi código

Compare con la respuesta anterior, esta es una razón clara (sobre la cual uno puede estar de acuerdo o en desacuerdo) para el uso de uno u otro (o ambos) tipos de excepciones.

Para ambas excepciones, crearé mi propia excepción no marcada y comprobada para mi aplicación (una buena práctica, como se menciona aquí ), a excepción de la excepción no verificada muy común (como NullPointerException)

Entonces, por ejemplo, el objetivo de esta función en particular a continuación es hacer (o obtener si ya existe) un objeto,
sentido:

  • el contenedor del objeto para hacer / obtener DEBE existir (responsabilidad del CALLER)
    => excepción no verificada, Y un comentario claro de javadoc para esta función llamada)
  • los otros parámetros no pueden ser nulos
    (Elección del codificador para poner eso en el CALLER: el codificador no verificará el parámetro nulo, pero el codificador LO HACE DOCUMENTAR)
  • el resultado NO PUEDE SER NULO
    (Responsabilidad y elección del código del destinatario, elección que será de gran interés para quien llama
    => marcada excepción porque todos los llamadores DEBEN tomar una decisión si el objeto no puede ser creado / encontrado, y esa decisión debe aplicarse en el momento de la compilación: no pueden usar esta función sin tener que lidiar con esta posibilidad, lo que significa que con esto excepción).

Ejemplo:

/** * Build a folder. <br /> * Folder located under a Parent Folder (either RootFolder or an existing Folder) * @param aFolderName name of folder * @param aPVob project vob containing folder (MUST NOT BE NULL) * @param aParent parent folder containing folder * (MUST NOT BE NULL, MUST BE IN THE SAME PVOB than aPvob) * @param aComment comment for folder (MUST NOT BE NULL) * @return a new folder or an existing one * @throws CCException if any problems occurs during folder creation * @throws AssertionFailedException if aParent is not in the same PVob * @throws NullPointerException if aPVob or aParent or aComment is null */ static public Folder makeOrGetFolder(final String aFoldername, final Folder aParent, final IPVob aPVob, final Comment aComment) throws CCException { Folder aFolderRes = null; if (aPVob.equals(aParent.getPVob() == false) { // UNCHECKED EXCEPTION because the caller failed to live up // to the documented entry criteria for this function Assert.isLegal(false, "parent Folder must be in the same PVob than " + aPVob); } final String ctcmd = "mkfolder " + aComment.getCommentOption() + " -in " + getPNameFromRepoObject(aParent) + " " + aPVob.getFullName(aFolderName); final Status st = getCleartool().executeCmd(ctcmd); if (st.status || StringUtils.strictContains(st.message,"already exists.")) { aFolderRes = Folder.getFolder(aFolderName, aPVob); } else { // CHECKED EXCEPTION because the callee failed to respect his contract throw new CCException.Error("Unable to make/get folder ''" + aFolderName + "''"); } return aFolderRes; }


Aquí hay una solución muy simple para su dilema Checked / Unchecked.

Regla 1: piense en una excepción sin marcar como una condición comprobable antes de que se ejecute el código. por ejemplo…

x.doSomething(); // the code throws a NullPointerException

donde x es nulo ... ... el código posiblemente tenga lo siguiente ...

if (x==null) { //do something below to make sure when x.doSomething() is executed, it won’t throw a NullPointerException. x = new X(); } x.doSomething();

Regla 2: piense en una excepción comprobada como una condición no comprobable que puede ocurrir mientras se ejecuta el código.

Socket s = new Socket(“google.com”, 80); InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream();

... en el ejemplo anterior, la URL (google.com) puede no estar disponible debido a que el servidor DNS está inactivo. Incluso en el instante en que el servidor DNS estaba funcionando y resolvió el nombre ''google.com'' en una dirección IP, si la conexión se realiza a google.com, en cualquier momento después de la palabra, la red podría caer. Simplemente no puede probar la red todo el tiempo antes de leer y escribir en transmisiones.

Hay momentos en los que el código simplemente debe ejecutarse antes de que podamos saber si hay un problema. Al forzar a los desarrolladores a escribir su código de tal manera que los obligue a manejar estas situaciones a través de la Excepción Controlada, tengo que recomendar al creador de Java que inventó este concepto.

En general, casi todas las API en Java siguen las 2 reglas anteriores. Si intenta escribir en un archivo, el disco podría llenarse antes de completar la escritura. Es posible que otros procesos hayan causado que el disco se llene. Simplemente no hay forma de probar esta situación. Para aquellos que interactúan con el hardware donde, en cualquier momento, el uso del hardware puede fallar, las Excepciones comprobadas parecen ser una solución elegante a este problema.

Hay un área gris para esto. En el caso de que se necesiten muchas pruebas (una declaración alucinante si con muchas && y ||), la excepción lanzada será una excepción CheckedException simplemente porque es demasiado doloroso para hacerlo bien: simplemente no se puede decir este problema. es un error de programación Si hay mucho menos de 10 pruebas (por ejemplo, ''if (x == null)''), entonces el error del programador debe ser una excepción sin marcar.

Las cosas se ponen interesantes cuando se trata de intérpretes de idiomas. De acuerdo con las reglas anteriores, ¿debería considerarse un error de sintaxis una excepción comprobada o no seleccionada? Yo diría que si la sintaxis del lenguaje se puede probar antes de que se ejecute, debería ser una excepción sin marcar. Si el idioma no se puede probar, de forma similar a cómo se ejecuta el código de ensamblado en una computadora personal, entonces el Error de sintaxis debe ser una excepción controlada.

Las 2 reglas anteriores probablemente eliminarán el 90% de su preocupación sobre la cual elegir. Para resumir las reglas, siga este patrón ... 1) si el código que se ejecutará se puede probar antes de que se ejecute para que se ejecute correctamente y si ocurre una excepción, también conocido como un error del programador, la excepción debe ser una excepción no comprobada (una subclase de RuntimeException ) 2) si el código que se ejecutará no se puede probar antes de que se ejecute para que se ejecute correctamente, la Excepción debe ser una Excepción Controlada (una subclase de Excepción).


Aquí quiero compartir mi opinión que tengo después de muchos años de experiencia en desarrollo:

  1. Excepción marcada. Esto es parte del caso de uso comercial o del flujo de llamadas, esto es parte de la lógica de la aplicación que esperamos o no esperamos. Por ejemplo, conexión rechazada, condición no satisfecha, etc. Necesitamos manejarlo y mostrar el mensaje correspondiente al usuario con instrucciones de lo que sucedió y qué hacer a continuación (intente de nuevo más tarde, etc.). Normalmente lo llamo excepción de post-procesamiento o excepción de "usuario".

  2. Excepción no verificada Esto es parte de la excepción de programación, un error en la programación del código del software (error, defecto) y refleja la forma en que los programadores deben usar la API según la documentación. Si un documento de lib / framework externo dice que espera obtener datos en algún rango y no son nulos, porque se lanzará NPE o IllegalArgumentException, el programador debe esperarlo y usar API correctamente según la documentación. De lo contrario, se lanzará la excepción. Normalmente lo llamo excepción de preprocesamiento o excepción de "validación".

Por público objetivo. Ahora hablemos sobre el público objetivo o grupo de personas a las que se han diseñado las excepciones (según mi opinión):

  1. Excepción marcada. La audiencia objetivo son usuarios / clientes.
  2. Excepción no verificada El público objetivo son los desarrolladores. Por otras palabras, la excepción sin marcar está diseñada solo para desarrolladores.

Por fase de ciclo de vida de desarrollo de aplicaciones.

  1. La excepción controlada está diseñada para existir durante todo el ciclo de vida de producción, como mecanismo normal y esperado que una aplicación maneja casos excepcionales.
  2. La excepción sin marcar está diseñada para existir solo durante el ciclo de vida de desarrollo / prueba de la aplicación, todas ellas deben repararse durante ese tiempo y no deben lanzarse cuando una aplicación ya se está ejecutando en producción.

La razón por la cual los marcos usualmente usan excepciones sin marcar (Spring por ejemplo) es que el framework no puede determinar la lógica de negocio de su aplicación, esto depende de los desarrolladores capturar y diseñar su propia lógica.


Creo que al declarar la Excepción de la aplicación debería ser la Excepción sin marcar, es decir, la subclase de RuntimeException. La razón es que no saturará el código de la aplicación con try-catch y throws declaration en el método. Si su aplicación usa Java Api, arroja excepciones comprobadas que de todos modos deben manejarse. Para otros casos, la aplicación puede lanzar una excepción sin marcar. Si la persona que llama a la aplicación aún necesita manejar una excepción no verificada, puede hacerlo.


Creo que podemos pensar en excepciones de varias preguntas:

¿Por qué ocurre la excepción? ¿Qué podemos hacer cuando sucede?

por error, un error. como se llama un método de objeto nulo.

String name = null; ... // some logics System.out.print(name.length()); // name is still null here

Este tipo de excepción se debe corregir durante la prueba. De lo contrario, se rompe la producción, y se obtiene un error muy alto que debe corregirse inmediatamente. Este tipo de excepciones no necesitan ser revisadas.

por entrada desde externa, no puede controlar ni confiar en la salida del servicio externo.

String name = ExternalService.getName(); // return null System.out.print(name.length()); // name is null here

Aquí, puede que necesite comprobar si el nombre es nulo si desea continuar cuando es nulo, de lo contrario, puede dejarlo solo y se detendrá aquí y le dará al llamante la excepción de tiempo de ejecución. Este tipo de excepciones no necesitan ser revisadas.

por excepción de tiempo de ejecución desde externo, no puede controlar ni confiar en el servicio externo.

Aquí, es posible que necesite detectar todas las excepciones de ExternalService si desea continuar cuando sucede, de lo contrario, puede dejarlo en paz y se detendrá aquí y le dará a la persona que llama la excepción de tiempo de ejecución.

mediante la excepción comprobada de externa, no puede controlar ni confiar en el servicio externo.

Aquí, es posible que necesite detectar todas las excepciones de ExternalService si desea continuar cuando sucede, de lo contrario, puede dejarlo en paz y se detendrá aquí y le dará a la persona que llama la excepción de tiempo de ejecución.

En este caso, ¿necesitamos saber qué tipo de excepción ocurrió en ExternalService? Depende:

  1. si puede manejar algunos tipos de excepciones, debe atraparlas y procesarlas. Para otros, burbujearlos.

  2. si necesita registrar o responder al usuario la ejecución específica, puede atraparlos. Para otros, burbujearlos.


De un aprendiz de Java :

Cuando ocurre una excepción, tiene que atrapar y manejar la excepción, o decirle al compilador que no puede manejarlo declarando que su método arroja esa excepción, entonces el código que usa su método tendrá que manejar esa excepción (incluso también puede optar por declarar que arroja la excepción si no puede manejarlo).

El compilador verificará que hayamos hecho una de las dos cosas (capturar, declarar). Entonces estas se llaman excepciones Checked. Pero el compilador no comprueba los errores y las excepciones de tiempo de ejecución (aunque puede optar por detectar o declarar, no es necesario). Por lo tanto, estos dos se llaman excepciones sin marcar.

Los errores se utilizan para representar las condiciones que ocurren fuera de la aplicación, como el bloqueo del sistema. Las excepciones de tiempo de ejecución generalmente se producen por error en la lógica de la aplicación. No puedes hacer nada en estas situaciones. Cuando se produce la excepción de tiempo de ejecución, debe volver a escribir el código de su programa. Entonces, estos no son verificados por el compilador. Estas excepciones de tiempo de ejecución se descubrirán durante el desarrollo y el período de prueba. Entonces tenemos que refactorizar nuestro código para eliminar estos errores.


En cualquier sistema lo suficientemente grande, con muchas capas, la excepción comprobada es inútil ya que, de todos modos, necesita una estrategia de nivel arquitectónico para manejar cómo se manejará la excepción (use una barrera de falla)

Con excepciones comprobadas, su estrategia de manejo de errores es microgestionada y es insoportable en cualquier sistema grande.

La mayoría de las veces no se sabe si un error es "recuperable" porque no se sabe en qué capa está ubicada la persona que llama de su API.

Digamos que creo una API StringToInt que convierte la representación de cadena de un entero en un Int. ¿Debo lanzar una excepción marcada si se llama a la API con la cadena "foo"? ¿Es recuperable? No sé porque en su capa la persona que llama de mi API StringToInt ya puede haber validado la entrada, y si se lanza esta excepción, es un error o una corrupción de datos y no es recuperable para esta capa.

En este caso, la persona que llama de la API no quiere detectar la excepción. Solo quiere dejar que la excepción "burbujee". Si selecciono una excepción marcada, esta persona tendrá un bloque de captura inútil solo para volver a lanzar artificialmente la excepción.

Lo que es recuperable depende la mayor parte del tiempo de la persona que llama de la API, no del creador de la API. Una API no debe usar excepciones comprobadas, ya que solo las excepciones sin marcar permiten elegir capturar o ignorar una excepción.


Estás en lo correcto.

Las excepciones no verificadas se utilizan para permitir que el sistema falle rápidamente, lo que es bueno. Debería indicar claramente qué espera su método para funcionar correctamente. De esta forma puede validar la entrada solo una vez.

Por ejemplo:

/** * @params operation - The operation to execute. * @throws IllegalArgumentException if the operation is "exit" */ public final void execute( String operation ) { if( "exit".equals(operation)){ throw new IllegalArgumentException("I told you not to..."); } this.operation = operation; ..... } private void secretCode(){ // we perform the operation. // at this point the opreation was validated already. // so we don''t worry that operation is "exit" ..... }

Solo para poner un ejemplo. El punto es que si el sistema falla rápidamente, sabrá dónde y por qué falló. Obtendrás un stacktrace como:

IllegalArgumentException: I told you not to use "exit" at some.package.AClass.execute(Aclass.java:5) at otherPackage.Otherlass.delegateTheWork(OtherClass.java:4569) ar ......

Y sabrá lo que sucedió. La OtherClass en el método "delegateTheWork" (en la línea 4569) llamó a su clase con el valor de "salida", incluso cuando no debería, etc.

De lo contrario, debería espolvorear validaciones en todo su código y eso es propenso a errores. Además, a veces es difícil hacer un seguimiento de lo que salió mal y puede esperar horas de depuración frustrante

Lo mismo sucede con NullPointerExceptions. Si tiene una clase de 700 líneas con unos 15 métodos, que usa 30 atributos y ninguno de ellos puede ser nulo, en lugar de validar en cada uno de esos métodos para la nulabilidad, puede hacer todos esos atributos de solo lectura y validarlos en el constructor o método de fábrica.

public static MyClass createInstane( Object data1, Object data2 /* etc */ ){ if( data1 == null ){ throw NullPointerException( "data1 cannot be null"); } } // the rest of the methods don''t validate data1 anymore. public void method1(){ // don''t worry, nothing is null .... } public void method2(){ // don''t worry, nothing is null .... } public void method3(){ // don''t worry, nothing is null .... }

Excepciones controladas Son útiles cuando el programador (usted o sus compañeros de trabajo) hicieron todo correctamente, validaron la entrada, realizaron pruebas y todo el código es perfecto, pero el código se conecta a un servicio web externo que puede estar inactivo (o un archivo) que estaba usando fue eliminado por otro proceso externo, etc.). El servicio web incluso puede ser validado antes de intentar la conexión, pero durante la transferencia de datos, algo salió mal.

En ese escenario, no hay nada que usted o sus colaboradores puedan hacer para ayudarlo. Pero aún tienes que hacer algo y no dejar que la aplicación simplemente muera y desaparezca a los ojos del usuario. Utiliza una excepción comprobada para eso y maneja la excepción, ¿qué puede hacer cuando eso sucede ?, la mayoría de las veces, solo para intentar registrar el error, probablemente guarde su trabajo (el trabajo de la aplicación) y presente un mensaje al usuario . (El sitio web está inactivo, vuelva a intentarlo más tarde, etc.)

Si la excepción marcada se usa en exceso (agregando el "throw Exception" en todas las firmas de métodos), entonces su código será muy frágil, porque todos ignorarán esa excepción (porque es demasiado general) y la calidad del código se tomará en serio comprometida.

Si usa una excepción no verificada, ocurrirá algo similar. Los usuarios de ese código no saben si algo puede salir mal y muchos try {...} catch (Throwable t) aparecerán.


Estoy de acuerdo con la preferencia de excepciones sin marcar como regla, especialmente al diseñar una API. La persona que llama siempre puede elegir atrapar una excepción documentada y sin marcar. Simplemente no estás obligando innecesariamente a la persona que llama.

Encuentro excepciones comprobadas útiles en el nivel inferior, como detalle de implementación. A menudo parece un mejor flujo de mecanismo de control que tener que administrar un error específico "código de retorno". A veces, también puede ayudar a ver el impacto de una idea para un cambio de código de bajo nivel ... declarar una excepción comprobada en sentido descendente y ver quién debería ajustarse. Este último punto no se aplica si hay una gran cantidad de genéricos: catch (Exception e) o throws Exception, que por lo general no está muy bien pensado de todos modos.


La regla que uso es: ¡nunca use excepciones sin marcar! (o cuando no ves ninguna forma de evitarlo)

Desde el punto de vista del desarrollador que usa su biblioteca o el usuario final que usa su biblioteca / aplicación, realmente apesta ser confrontado con una aplicación que se bloquea debido a una excepción no demandada. Y contar con una trampa no es bueno tampoco.

De esta forma, el usuario final aún puede recibir un mensaje de error, en lugar de que la aplicación desaparezca por completo.


Las excepciones comprobadas son geniales, siempre que comprenda cuándo se deben usar. La API central de Java no sigue estas reglas para SQLException (y a veces para IOException) y es por eso que son tan terribles.

Las excepciones controladas se deben usar para predecir errores inevitables de los que sea razonable recuperar .

Las excepciones no verificadas se deben usar para todo lo demás.

Voy a analizar esto por ti, porque la mayoría de la gente entiende mal lo que esto significa.

  1. Predecible pero inevitable : la persona que llama hizo todo lo que estuvo a su alcance para validar los parámetros de entrada, pero alguna condición fuera de su control ha causado que la operación falle. Por ejemplo, intenta leer un archivo, pero alguien lo elimina entre el momento en que comprueba si existe y el momento en que comienza la operación de lectura. Al declarar una excepción marcada, le está diciendo a la persona que llama que anticipe esta falla.
  2. Es razonable recuperarse de : no tiene sentido pedirles a las personas que llaman que anticipen excepciones de las que no puedan recuperarse. Si un usuario intenta leer desde un archivo no existente, la persona que llama puede solicitar un nuevo nombre de archivo. Por otro lado, si el método falla debido a un error de programación (argumentos de método no válidos o implementación de método erróneo) no hay nada que la aplicación pueda hacer para solucionar el problema en mitad de la ejecución. Lo mejor que puede hacer es registrar el problema y esperar a que el desarrollador lo solucione en un momento posterior.

A menos que la excepción que está lanzando cumpla con todas las condiciones anteriores, debería usar una excepción no seleccionada.

Reevaluar en todos los niveles : en ocasiones, el método que detecta la excepción comprobada no es el lugar correcto para manejar el error. En ese caso, considere lo que es razonable para sus propios llamadores. Si la excepción es predecible, inevitable y razonable para que se recupere a partir de entonces, debe lanzar usted mismo una excepción marcada. De lo contrario, debe ajustar la excepción en una excepción sin marcar. Si sigues esta regla, te encontrarás convirtiendo excepciones marcadas en excepciones sin marcar y viceversa, dependiendo de la capa en la que te encuentres.

Para las excepciones marcadas y sin marcar, use el nivel de abstracción correcto . Por ejemplo, un depósito de código con dos implementaciones diferentes (base de datos y sistema de archivos) debe evitar exponer detalles específicos de la implementación lanzando SQLException o IOException . En cambio, debe envolver la excepción en una abstracción que abarque todas las implementaciones (por ejemplo, RepositoryException ).


Las excepciones controladas son útiles para casos recuperables en los que desea proporcionar información a la persona que llama (es decir, permisos insuficientes, archivo no encontrado, etc.).

Las excepciones no verificadas se usan raramente, en todo caso, para informar al usuario o programador de errores graves o condiciones inesperadas durante el tiempo de ejecución. No los arroje si está escribiendo códigos o bibliotecas que serán utilizados por otros, ya que es posible que no esperen que su software arroje excepciones no verificadas ya que el compilador no los fuerza a ser capturados o declarados.


No se trata solo de la capacidad de recuperarse de la excepción. Lo que más importa, en mi opinión, es si la persona que llama está interesada en captar la excepción o no.

Si escribe una biblioteca para usar en otro lugar, o una capa de nivel inferior en su aplicación, pregúntese si la persona que llama está interesada en conocer (conocer) su excepción. Si no lo está, entonces use una excepción sin marcar, para que no lo cargue innecesariamente.

Esta es la filosofía utilizada por muchos marcos. Spring e hibernate, en particular, me vienen a la mente: convierten la excepción comprobada conocida en una excepción sin marcar precisamente porque las excepciones marcadas se usan en exceso en Java. Un ejemplo en el que puedo pensar es la JSONException de json.org, que es una excepción comprobada y es en su mayoría molesta, debe ser desmarcada, pero el desarrollador simplemente no lo ha pensado bien.

Por cierto, la mayor parte del tiempo el interés de la persona que llama en la excepción se correlaciona directamente con la capacidad de recuperación de la excepción, pero ese no es siempre el caso.


Puede llamarlo una excepción marcada o no marcada; sin embargo, ambos tipos de excepción pueden ser captados por el programador, por lo que la mejor respuesta es: escriba todas sus excepciones sin marcar y documentarlas. De esta forma, el desarrollador que usa su API puede elegir si desea detectar esa excepción y hacer algo. Las excepciones comprobadas son un desperdicio completo del tiempo de todos y hacen que su código sea una pesadilla impactante a la vista. Las pruebas de unidades adecuadas mostrarán las excepciones que pueda tener para atrapar y hacer algo.


Siempre que sea menos probable que se espere una excepción, y podemos proceder incluso después de detectar eso, y no podemos hacer nada para evitar esa excepción, entonces podemos usar la excepción marcada.

Cuando queremos hacer algo significativo cuando ocurre una excepción en particular y cuando se espera esa excepción pero no es cierta, podemos usar la excepción marcada.

Siempre que la excepción navegue en diferentes capas, no es necesario que la capturemos en cada capa, en ese caso, podemos usar la excepción de tiempo de ejecución o envolver la excepción como excepción no verificada.

La excepción en tiempo de ejecución se utiliza cuando es más probable que se produzca una excepción, no hay forma de ir más allá y nada puede recuperarse. Entonces, en este caso, podemos tomar precauciones con respecto a esa excepción. EX: NUllPointerException, ArrayOutofBoundsException. Es más probable que sucedan. En este escenario, podemos tomar precauciones mientras codificamos para evitar tal excepción. De lo contrario, tendremos que escribir try catch blocks en todos lados.

Se pueden hacer excepciones más generales. Sin marcar, se verifican menos generales.


Excepción comprobada: si el cliente puede recuperarse de una excepción y desea continuar, use la excepción marcada.

Excepción no verificada: si un cliente no puede hacer nada después de la excepción, suba la excepción no verificada.

Ejemplo: si se espera que haga una operación aritmética en un método A () y en función de la salida de A (), tiene que realizar otra operación. Si la salida es nula del método A () que no está esperando durante el tiempo de ejecución, entonces se espera que ejecute Excepción de puntero nulo, que es excepción de tiempo de ejecución.

Consulte here