【问题标题】:Accessing variables from inner class从内部类访问变量
【发布时间】:2011-06-15 10:57:58
【问题描述】:

我有一些代码为回调处理程序定义了一个匿名内部类。这个处理程序需要分配一个局部变量,见下文。我需要在回调中分配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());
    }
}

【问题讨论】:

    标签: java inner-classes anonymous-inner-class


    【解决方案1】:

    您可以通过为响应创建一个包装类来解决这个问题。

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

    【讨论】:

    • ResponseWrapper 需要初始化。
    【解决方案2】:

    假设这是您要更改的代码,如何更改 sendRequestResponseAction.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());
        }
    }
    

    【讨论】:

      【解决方案3】:

      以下是适用于您的情况的 hack:

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

      但是,如果您想要一个更简洁的解决方案,您必须为您的处理程序定义一个命名类,将响应存储在其字段中,并使用访问器方法检索它。

      最好的问候, 斯坦。

      【讨论】:

      • 有趣的破解;为什么数组有效,而简单变量无效?
      • 因为您没有修改 resp[] 指向的最终引用。
      【解决方案4】:

      如果要返回结果,请使用命名内部类而不是匿名内部类。提供的所有其他选项都是恕我直言丑陋的黑客(一个自我承认;-)

      (好吧,@Joel 不是,但假设您可以更改正在实现的接口)

      只需为结果创建一个带有 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());
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-04
        • 2015-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-25
        • 2011-11-01
        相关资源
        最近更新 更多