tubos trampas trampa ratones ratas pvc precio pegamento pega para minutos hacer grandes gel con como botellas atrapar adhesivo java generics exception exception-handling try-catch

java - ratones - trampas para ratas con tubos pvc



¿Por qué no puedo tener una trampa para una excepción marcada para una llamada que arroja un genérico? (2)

Este comportamiento se especifica en la sección 11.2.3 de JLS :

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 Exception o una superclase de Exception .

MyCheckedException ajusta a la descripción de la clase E1 anterior, porque no está declarado en la declaración genérica de processable.apply() , y no es Exception o una de sus superclases. El compilador solo sabe que el método puede arrojar un Throwable , por lo que MyCheckedException no se declara.

Estoy trabajando en un pequeño helper que se supone que invoque código arbitrario (pasado como lambda). El ayudante debería detectar ciertas excepciones y arrojarlas dentro de un envoltorio. Mis "propias" excepciones no deberían envolverse sino simplemente volverse a lanzar.

Se me ocurrió este código:

@FunctionalInterface interface Processable<T, X extends Throwable> { public T apply() throws X; } class MyCheckedException extends Exception { ... } class MyCheckedExceptionWrapper extends MyCheckedException { ... } public class MyExceptionLogger<T, X extends Throwable> { public T process(Processable<T, X> processable) throws MyCheckedException { try { return processable.apply(); } catch (MyCheckedException thrown) { // this line isn''t accepted throw thrown; } catch (Exception | LinkageError thrown) { throw new MyCheckedExceptionWrapper(thrown); } catch (Throwable thrown) { ... just log return null; } } }

Lo anterior da un error de compilación:

Bloque catch inaccesible para MyCheckedException. Esta excepción nunca se lanza desde el cuerpo de la declaración try MyExceptionLogger ...

En otras palabras: aunque apply() se define para lanzar algo, X extends Throwable I no puede detectar una excepción específica marcada al invocar ese método.

que puedo llegar al código de trabajo atrapando a Throwable , para luego usar una instanceof verificación, pero me gustaría entender por qué no es posible hacer una prueba / captura como se describe anteriormente.


Creo que hay, basado en el JSL, una buena razón por la que no debería poder detectar su excepción marcada personalizada en su ejemplo.

Si lees la cita del JLS

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 Exception o una superclase de Exception .

Se debe permitir que una cláusula catch capture cualquier Exception marcada, si un método en el try-block correspondiente declara Throwable . En su ejemplo, el try-block puede arrojar una clase de excepción comprobada que sea una subclase o una superclase de MyCheckedException concretamente MyCheckedException y MyCheckedException obviamente no es una Exception o una superclase de Exception

Esto se puede verificar fácilmente eliminando los genéricos del ejemplo anterior y compilando sin problemas:

@FunctionalInterface interface Processable<T> { public T apply() throws Throwable; } private <T> T process(Processable<T> aProcessable) { try { return aProcessable.apply(); } catch (MyCheckedException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } catch (Throwable e) { e.printStackTrace(); } return null; }

Ese es el problema de alguna manera tiene que estar relacionado con el uso de genéricos en combinación con excepciones. Tal vez esto esté relacionado con el borrado de tipos, pero con los tipos borrados su ejemplo también funciona bien:

@FunctionalInterface interface Processable { public Object apply() throws Throwable; } private Object process(Processable aProcessable) { try { return aProcessable.apply(); } catch (MyCheckedException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } catch (Throwable e) { e.printStackTrace(); } return null; }