2011-01-25 2 views
10

У меня есть код, который определяет анонимный внутренний класс для обработчика обратного вызова. Этот обработчик должен назначить локальную переменную, см. Ниже. Мне нужно назначить resp в обратном вызове и обратиться к нему в конце функции. Я получаю эту ошибку в Eclipse, однако:Доступ к переменным из внутреннего класса

Конечный локальный переменная resp не может быть назначен, так как она определена в типе ограждающей

Как я могу это исправить?

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()); 
    } 
} 

ответ

3

Вы можете обойти это, создав класс оболочки для ответа.

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

Затем, ваш код будет выглядеть следующим образом:

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 должен быть инициализирован. – Joel

+0

@Joel, спасибо, что указали это. Исправлена. – jjnguy

+0

@ Эрик, почему бы не работать? – jjnguy

1

Предполагая, что это ваш код, чтобы изменить, как об изменении sendRequest и ResponseAction.execute вернуть экземпляр 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

Здесь это взлом, который будет работать в вашем случае:

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()); 
    } 
} 

Если вам требуется более чистое решение, вы должны определить именованный класс для своего обработчика, сохранить ответ в своем поле и получить его с помощью метода доступа.

С уважением, Stan.

+3

Интересный взлом; почему массив работает, но простая переменная не работает? –

+3

, потому что вы не изменяете окончательную ссылку, которая также соответствует []. – Joel

0

Если вы хотите вернуть результаты, используйте вместо имени анонимный внутренний класс. Все другие варианты, представленные в IMHO уродливого хаки (один самостоятельной признал ;-)

(OK, @ Джоэл не является, но предполагает, что вы можете изменить интерфейс вы реализующий)

Просто создать экземпляр класса с getter для результата, он чист и требует только одного класса.

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

Ты слишком добрый! – Joel

Смежные вопросы