2011-11-12 23 views
6

Qual è il modo migliore per ottenere Exception Transparency in Java quando si utilizza una classe interna anonima per eseguire codice.Thinging Checked Exceptions from Anonimo Inner Classes

Uno schema frequente che ho visto nel codice reale è l'utilizzo di alcune interfacce tipo pseudo Runnable per specificare un contesto per un determinato codice. L'esempio migliore che riesco a pensare nel JDK è 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 
    } 
} 

Anche se la lettura del codice si può chiaramente vedere il codice interno getta solo un file non trovato, ma abbiamo perso i benefici di eccezioni controllate come il chiamante non è a conoscenza di ciò che è in realtà un'eccezione gettata. Un bug comune sarebbe quello di introdurre il codice nella classe interna anonima che genererebbe una nuova eccezione e il codice non forzerebbe a gestire quell'eccezione.

Quello che voglio è qualcosa di simile a ciò che è sotto, è questo tipo di comportamento raggiungibile senza un cambio di lingua?

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

Penso che le classi interne anonime siano, in generale, una cattiva idea, principalmente perché non possono essere riutilizzate o estese. Ma questa è un'altra ragione. Sono interessato anche a qualsiasi risposta. – user949300

+0

Dai un'occhiata a http://blogs.sun.com/briangoetz/entry/exception_transparency_in_java – alexsmail

+0

Ho visto la proposta di Brian sotto progetto lambda, purtroppo questo non è disponibile in java 6 – bluphoenix

risposta

3

Non vedo perché no. Il seguente codice ha funzionato.

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

Cosa faresti se dovessi lanciare più di un'eccezione? Avresti un RunIt2 . Immagino che non sia poi così male. Dovrei scegliere quale interfaccia usare a seconda di quali eccezioni controllate mi aspetto di lanciare. – bluphoenix

+0

Se è necessario lanciare più di un'eccezione, ci sono 2 opzioni. (1) mentre si dice che E1 estende Eccezione, E2 estende Eccezione. (2) Potresti scegliere E per essere una super classe di tutte le eccezioni che potrebbero essere lanciate. Se si seleziona 1, l'interfaccia potrebbe essere simile a RunIt per consentire molti tipi di eccezioni controllate. (Se ce ne sono più del necessario, è possibile impostare l'eccesso su RuntimeException.) Se si sceglie 2 quel tipo di sconfitte lo scopo dell'esercizio. Non è una grande soluzione, ma funziona. – emory