Доступ к переменным из внутреннего класса - PullRequest
10 голосов
/ 25 января 2011

У меня есть некоторый код, который определяет анонимный внутренний класс для обработчика обратного вызова.Этот обработчик должен назначить локальную переменную, см. Ниже.Мне нужно присвоить 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());
    }
}

Ответы [ 4 ]

5 голосов
/ 25 января 2011

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

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

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

С уважением, Стэн.

3 голосов
/ 25 января 2011

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

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());
}
1 голос
/ 25 января 2011

Предполагая, что это ваш код для изменения, как насчет изменения 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());
    }
}
0 голосов
/ 26 января 2011

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

(ОК, @ Joel's нет, но предполагает, что вы можете изменить интерфейс, который вы реализуете)

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

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