2011-11-12 16 views
6

¿Cuál es la mejor forma de obtener transparencia de excepciones en Java cuando se usa una clase interna anónima para ejecutar algún código?Lanzar excepciones comprobadas de clases internas anónimas

Un patrón frecuente que he visto en el código real es el uso de alguna interfaz pseudo Ejecutable para especificar el contexto de algún código dado. El mejor ejemplo que puedo pensar en el JDK es java.security.PrivilegedExceptionAction.

try { 
    boolean success = AccessController.doPrivileged(
     new PrivilegedExceptionAction<Boolean>() { 
      @Override 
      public Boolean run() throws Exception { 
       // do something 
       // read file 
       FileInputStream fileInputStream = 
        new FileInputStream(new File("someFile")); 
       return true; 
      } 
     } 
    ); 
} catch (PrivilegedActionException e) { 
    if (e.getCause() instanceof FileNotFoundException) { 
     // handle IO exception 
    } else { 
     // impossible no other checked exception 
    } 
} 

A pesar de que la lectura del código se puede ver claramente el código interno no hace más de un archivo no encontrado, pero hemos perdido los beneficios de excepciones comprobadas como la persona que llama no es consciente de lo que es en realidad una excepción lanzada. Un error común sería introducir código en la clase interna anónima que lanzaría una nueva excepción y el código no lo forzaría a manejar esa excepción.

Lo que quiero es algo como lo que sigue, ¿se puede lograr este tipo de comportamiento sin un cambio de idioma?

public interface PrivilegedExceptionAction<T,V... extends Throwable> 
{ 
    public T run() throws V; 
} 
+0

Creo que las clases internas anónimas son, en general, una mala idea, principalmente porque no se pueden reutilizar ni ampliar. Pero esta es otra razón. Estoy interesado en cualquier respuesta también. – user949300

+0

Echa un vistazo en http://blogs.sun.com/briangoetz/entry/exception_transparency_in_java – alexsmail

+0

He visto la propuesta de Brian en el proyecto lambda, lamentablemente esto no está disponible en java 6 – bluphoenix

Respuesta

3

No veo por qué no. El siguiente código funcionó.

interface RunIt < E extends Exception > 
{ 
    void run () throws E ; 
} 

class App 
{ 
    public static void main (String [ ] args) 
    { 
     RunIt <RuntimeException> r = new RunIt <RuntimeException> () 
     { 
      public void run () 
      { 
       throw new RuntimeException () ; 
      } 
     } ; 
     r . run () ; 
    } 
} 
+0

¿Qué harías si necesitas lanzar más de una excepción? ¿Tendría un RunIt2 . Supongo que eso no es tan malo. Tendría que elegir qué interfaz usar dependiendo de las excepciones marcadas que espero lanzar. – bluphoenix

+0

Si necesita lanzar más de una excepción, hay 2 opciones. (1) cuando dice que E1 amplía Exception, E2 amplía Exception. (2) Puede elegir E para ser una súper clase de todas las excepciones que podrían arrojarse. Si elige 1, entonces la interfaz podría verse como RunIt para permitir una gran cantidad de tipos de excepciones marcadas. (Si hay más de lo que necesita, puede establecer el exceso en RuntimeException.) Si elige 2, ese tipo de derrota el propósito del ejercicio. No es una gran solución, pero funciona. – emory

Cuestiones relacionadas