try todas tipos propagacion personalizadas para numeros negativos mas lista las excepciones comunes catch java exception try-catch checked-exceptions unchecked-exception

tipos - todas las excepciones en java



¿Por qué se marcan las excepciones controladas permitidas para el código que no arroja excepciones? (3)

Citando la Especificación del Lenguaje Java, §11.2.3 :

Es un error en tiempo de compilación si una cláusula de captura puede detectar la clase de excepción comprobada E1 y no es el caso que el bloque try correspondiente a la cláusula catch pueda arrojar una clase de excepción comprobada que sea una subclase o superclase de E1, a menos que E1 Excepción o una superclase de Excepción.

Supongo que esta regla se originó mucho antes que Java 7, donde las capturas múltiples no existían. Por lo tanto, si tuviera un bloque try que arrojara una multitud de excepciones, la forma más fácil de capturar todo sería capturar una superclase común (en el peor de los casos, Exception o Throwable si también quiere detectar Error s).

Tenga en cuenta que es posible que no capte un tipo de excepción que no esté relacionado con lo que se arroja realmente: en su ejemplo, capturar cualquier subclase de Throwable que no sea una RuntimeException será un error:

try { System.out.println("hello"); } catch (IOException e) { // compilation error e.printStackTrace(); } Editar por OP: la parte principal de la respuesta es el hecho de que los ejemplos de preguntas funcionan solo para la clase Excepción. Generalmente no se permite capturar excepciones comprobadas en lugares aleatorios del código. Perdón si confundí a alguien usando estos ejemplos.

En Java, los métodos que lanzan excepciones controladas ( Exception o sus subtipos - IOException, InterruptedException, etc.) deben declarar throws statement:

public abstract int read() throws IOException;

Los métodos que no declaran arrojar declaración no pueden arrojar excepciones marcadas.

public int read() { // does not compile throw new IOException(); } // Error: unreported exception java.io.IOException; must be caught or declared to be thrown

Pero detectar excepciones comprobadas en métodos seguros sigue siendo legal en Java:

public void safeMethod() { System.out.println("I''m safe"); } public void test() { // method guarantees not to throw checked exceptions try { safeMethod(); } catch (Exception e) { // catching checked exception java.lang.Exception throw e; // so I can throw... a checked Exception? } }

En realidad no. Es un poco divertido: el compilador sabe que e no es una excepción comprobada y permite volver a lanzarlo. Las cosas son incluso un poco ridículas, este código no se compila:

public void test() { // guarantees not to throw checked exceptions try { safeMethod(); } catch (Exception e) { throw (Exception) e; // seriously? } } // Error: unreported exception java.lang.Exception; must be caught or declared to be thrown

El primer fragmento fue una motivación para una pregunta.

El compilador sabe que las excepciones comprobadas no pueden arrojarse dentro de un método seguro, por lo que tal vez debería permitir capturar solo las excepciones no verificadas.

Volviendo a la pregunta principal , ¿hay alguna razón para implementar la captura de excepciones marcadas de esta manera? ¿Es solo un defecto en el diseño o me faltan algunos factores importantes, tal vez incompatibilidades hacia atrás? ¿Qué podría salir mal si solo RuntimeException fuera atrapada en este escenario? Los ejemplos son muy apreciados.


El problema aquí es que las limitaciones de las excepciones controladas / no comprobadas afectan a lo que su código puede arrojar , no a lo que está permitido atrapar . Si bien aún puede atrapar cualquier tipo de Exception , las únicas que puede arrojar de nuevo son las que no se marcaron. (Esta es la razón por la que convertir su excepción no verificada en una excepción marcada rompe su código).

Capturar una excepción sin marcar con Exception es válida, porque las excepciones sin marcar (también conocidas como RuntimeException s) son una subclase de Exception, y sigue las reglas de polimorfismo estándar; no convierte la excepción capturada en una Exception , del mismo modo que almacenar una String en un Object no convierte la String en un Object . Polimorfismo significa que una variable que puede contener un Object puede contener cualquier cosa derivada de un Object (como una String ). Del mismo modo, como Exception es la superclase de todos los tipos de excepción, una variable de tipo Exception puede contener cualquier clase derivada de Exception , sin convertir el objeto en una Exception . Considera esto:

import java.lang.*; // ... public String iReturnAString() { return "Consider this!"; } // ... Object o = iReturnAString();

A pesar de que el tipo de variable es Object , o aún almacena una String , ¿no es así? Del mismo modo, en tu código:

try { safeMethod(); } catch (Exception e) { // catching checked exception throw e; // so I can throw... a checked Exception? }

Lo que esto significa es en realidad "capturar cualquier cosa compatible con Exception clase (es decir, Exception y todo lo que se derive de ella)". Lógica similar se usa en otros idiomas, también; por ejemplo, en C ++, la captura de std::exception también detectará std::runtime_error , std::logic_error , std::bad_alloc , cualquier excepción creada por el usuario definida correctamente, etc., porque todas derivan de std::exception

tl; dr: no está detectando excepciones controladas , está atrapando excepciones. La excepción solo se convierte en una excepción comprobada si la convierte en un tipo de excepción comprobada.


Java 7 introdujo una comprobación de tipo de excepción más inclusiva .

Sin embargo, en Java SE 7, puede especificar los tipos de excepción FirstException y SecondException en la cláusula throws en la declaración del método rethrowException. El compilador de Java SE 7 puede determinar que la excepción lanzada por la instrucción throw e debe provenir del bloque try, y que las únicas excepciones lanzadas por el bloque try pueden ser FirstException y SecondException.

Este pasaje habla de un bloque try que arroja específicamente FirstException y SecondException ; aunque el bloque catch arroja Exception , el método solo necesita declarar que arroja FirstException y SecondException , no Exception :

public void rethrowException(String exceptionName) throws FirstException, SecondException { try { // ... } catch (Exception e) { throw e; } }

Esto significa que el compilador puede detectar que los únicos tipos de excepción posibles lanzados en la test son Error s o RuntimeException s, ninguno de los cuales debe capturarse. Cuando throw e; , puede decir, incluso cuando el tipo estático es Exception , que no necesita ser declarado o vuelto a capturar.

Pero cuando lo lanzas a Exception , esto pasa por alto esa lógica. Ahora el compilador lo trata como una Exception ordinaria que debe capturarse o declararse.

La razón principal para agregar esta lógica al compilador era permitirle al programador especificar solo subtipos específicos en la cláusula throws al volver a lanzar una Exception general que capture esos subtipos específicos. Sin embargo, en este caso, le permite capturar una Exception general y no tener que declarar ninguna excepción en una cláusula throws , porque no se marcan los tipos específicos que se pueden marcar como excepciones.