Gewone uitzonderingen van anonieme innerlijke klassen weggooien

Wat is de beste manier om Exception Transparency in Java te krijgen wanneer je een anonieme innerlijke klasse gebruikt om wat code uit te voeren.

Een veelvoorkomend patroon dat ik in echte code heb gezien, is het gebruik van een pseudo-interface van het type Runnable om een ​​bepaalde context voor een gegeven code te specificeren. Het beste voorbeeld dat ik kan bedenken in de JDK is de java.security.PrivilegedExceptionAction.

try {
    boolean success = AccessController.doPrivileged(
        new PrivilegedExceptionAction() {
            @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
    }
}

Hoewel je de code leest, kun je duidelijk zien dat de innerlijke code alleen een bestand genereert dat niet is gevonden, maar we hebben de voordelen van gecontroleerde uitzonderingen verloren omdat de beller niet weet welke uitzondering daadwerkelijk wordt gegenereerd. Een veel voorkomende bug zou zijn om code in te voeren in de anonieme inner klasse die een nieuwe uitzondering zou opleveren en de code zou je niet dwingen om met die uitzondering om te gaan.

Wat ik wil, is zoiets als wat hieronder staat, is dit soort gedrag haalbaar zonder een taalverandering?

public interface PrivilegedExceptionAction
{
    public T run() throws V;
}
6
Ik denk dat anonieme innerlijke klassen over het algemeen een slecht idee zijn, vooral omdat ze niet kunnen worden hergebruikt of uitgebreid. Maar dit is nog een reden. Ik ben ook geïnteresseerd in elk antwoord.
toegevoegd de auteur user949300, de bron
toegevoegd de auteur alexsmail, de bron
sun.com links zijn nu dood. Het genoemde artikel is nu hier blogs.oracle.com/briangoetz/entry/…
toegevoegd de auteur GeneSys, de bron
Ik heb het voorstel van Brian onder project lambda gezien, helaas is dit niet beschikbaar in Java 6
toegevoegd de auteur bluphoenix, de bron

1 antwoord

Ik begrijp niet waarom niet. De volgende code werkte.

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 ( ) ;
    }
}
3
toegevoegd
Als je meer dan één uitzondering wilt gooien, zijn er 2 opties. (1) terwijl je zegt dat E1 Exception verlengt, breidt E2 Exception uit. (2) Je zou E kunnen kiezen als een superklasse van alle uitzonderingen die zouden kunnen worden gegooid. Als u 1 kiest, ziet de interface er misschien als RunIt uit om een ​​groot aantal soorten gecontroleerde uitzonderingen toe te staan. (Als er meer zijn dan je nodig hebt, kun je het eigen risico instellen op RuntimeException.) Als je 2 kiest, verslaat dit het doel van de oefening. Het is geen geweldige oplossing, maar het werkt.
toegevoegd de auteur emory, de bron
Wat zou u doen als u meer dan één uitzondering moet maken? Zou u een RunIt2 hebben . Ik denk dat dat niet zo erg is. Ik zou moeten kiezen welke interface ik moet gebruiken, afhankelijk van de gecontroleerde uitzonderingen die ik verwacht te gooien.
toegevoegd de auteur bluphoenix, de bron