2011-01-25 18 views
10

Ho un codice che definisce una classe interna anonima per un gestore di callback. Questo gestore deve assegnare una variabile locale, vedi sotto. Devo assegnare resp nel callback e fare riferimento ad esso verso la fine della funzione. Sto ottenendo questo errore in Eclipse però:Accesso alle variabili dalla classe interna

La finale variabile locale resp non può essere assegnato, dal momento che è definito in un tipo di inclusione

Come posso risolvere questo problema?

DoorResult unlockDoor(final LockableDoor door) { 
    final UnlockDoorResponse resp; 
    final boolean sent = sendRequest(new UnlockDoorRequest(door), 
     new ResponseAction() { 
     public void execute(Session session) 
       throws TimedOutException, RetryException, RecoverException { 
      session.watch(UNLOCK_DOOR); 
      resp = (UnlockDoorResponse)session.watch(UNLOCK_DOOR); 
     } 
    }); 
    DoorResult result; 
    if (!sent) { 
     return DoorResult.COMMS_ERROR; 
    } 
    else { 
     return DoorResult.valueOf(resp.getResponseCode()); 
    } 
} 

risposta

3

È possibile aggirare questo creando una classe wrapper per la risposta.

class ResponseWrapper { 
    UnlockDoorResponse resp; 
    void setResponse(UnlockDoorResponse resp) { 
     this.resp = resp; 
    } 
    UnlockDoorResponse getResponse() { 
     return resp; 
    } 
} 

Poi, il codice sarà simile:

final ResponseWrapper respWrap = new ResponseWrapper(); 
final boolean sent = sendRequest(new UnlockDoorRequest(door), new ResponseAction() { 
    public void execute(Session session) throws TimedOutException, RetryException, RecoverException { 
     session.watch(UNLOCK_DOOR); 
     respWrap.setResponse((UnlockDoorResponse)session.watch(UNLOCK_DOOR)); 
    } 
}); 
DoorResult result; 
if (!sent) { 
    return DoorResult.COMMS_ERROR; 
} 
else { 
    return DoorResult.valueOf(respWrap.getResponse().getResponseCode()); 
} 
+0

ResponseWrapper deve essere inizializzato. – Joel

+0

@ Joel, grazie per averlo indicato. Fisso. – jjnguy

+0

@Erick, perché non dovrebbe funzionare? – jjnguy

1

Supponendo che questo è il codice per cambiare, come di cambiare sendRequest e ResponseAction.execute per restituire un'istanza di UnlockDoorResponse

DoorResult unlockDoor(final LockableDoor door) { 
    final UnlockDoorResponse resp = sendRequest(new UnlockDoorRequest(door), new ResponseAction() { 
     public UnlockDoorResponse execute(Session session) throws TimedOutException, RetryException, RecoverException { 
      session.watch(UNLOCK_DOOR); 
      return (UnlockDoorResponse)session.watch(UNLOCK_DOOR); 
     } 
    }); 
    if (resp == null) { 
     return DoorResult.COMMS_ERROR; 
    } 
    else { 
     return DoorResult.valueOf(resp.getResponseCode()); 
    } 
} 
5

Qui è un trucco che potrebbe funzionare nel tuo caso:

DoorResult unlockDoor(final LockableDoor door) { 
    final UnlockDoorResponse resp[] = { null }; 
    final boolean sent = sendRequest(new UnlockDoorRequest(door), new ResponseAction() { 
     public void execute(Session session) throws TimedOutException, RetryException, RecoverException { 
      session.watch(UNLOCK_DOOR); 
      resp[0] = (UnlockDoorResponse)session.watch(UNLOCK_DOOR); 
     } 
    }); 
    DoorResult result; 
    if (!sent) { 
     return DoorResult.COMMS_ERROR; 
    } 
    else { 
     return null == resp[0] ? null : DoorResult.valueOf(resp[0].getResponseCode()); 
    } 
} 

Se si desidera una soluzione più pulita, tuttavia, è necessario definire una classe denominata per il gestore, archiviare la risposta nel relativo campo e recuperarla utilizzando un metodo accessor.

Cordiali saluti, Stan.

+3

Interessante mod; perché la matrice funziona ma la variabile semplice no? –

+3

perché non stai modificando il riferimento finale che risponda anche a []. – Joel

0

Se si restituiscono risultati, utilizzare una classe interna denominata anziché anonima. Tutte le altre opzioni presentate sono IMHO brutte hack (un'auto ammesso ;-)

(OK, @ Joel non è, ma si assume è possibile modificare l'interfaccia che si sta implementando)

Basta creare un'istanza della classe con un getter per il risultato, è pulito e richiede solo di implementare la singola classe.

class MyReponseAction implements ResponseAction { 
     private UnlockDoorResponse response; 

     public void execute(Session session) throws TimedOutException, RetryException, RecoverException { 
      session.watch(UNLOCK_DOOR); 
      response = (UnlockDoorResponse)session.watch(UNLOCK_DOOR); 
     } 

     UnlockDoorResponse getResponse() { 
      return response; 
     } 
    } 

    DoorResult unlockDoor(final LockableDoor door) { 
     ResponseAction action = new MyResponseAction(); 
     final boolean sent = sendRequest(new UnlockDoorRequest(door), action); 

     DoorResult result; 
     if (!sent) { 
      return DoorResult.COMMS_ERROR; 
     } 
     else { 
      return DoorResult.valueOf(action.getResponse().getResponseCode()); 
     } 
    } 
+0

Sei troppo gentile! – Joel