java 从内部类访问变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4798249/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 08:04:17  来源:igfitidea点击:

Accessing variables from inner class

javainner-classesanonymous-inner-class

提问by fred basset

I've got some code which defines an anonymous inner class for a callback handler. This handler needs to assign a local variable, see below. I need to assign respin the callback and refer to it towards the end of the function. I am getting this error in Eclipse however:

我有一些代码为回调处理程序定义了一个匿名内部类。这个处理程序需要分配一个局部变量,见下文。我需要resp在回调中分配并在函数结束时引用它。但是,我在 Eclipse 中收到此错误:

The final local variable respcannot be assigned, since it is defined in an enclosing type

resp无法分配最终局部变量,因为它是在封闭类型中定义的

How can I fix this?

我怎样才能解决这个问题?

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

回答by Stan

Here is a hack that would work in your case:

这是一个适用于您的情况的黑客:

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

If you want a cleaner solution, though, you have to define a named class for your handler, store the response in its field, and retrieve it using an accessor method.

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

Best regards, Stan.

最好的问候,斯坦。

回答by jjnguy

You could get around this by creating a wrapper class for the response.

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

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

Then, your code would look like:

然后,您的代码将如下所示:

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

回答by Joel

Assuming this is your code to change, how about changing sendRequestand ResponseAction.executeto return an instance of UnlockDoorResponse

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

回答by Robin

If you are going to return results, then use a named inner class instead of an anonymous one. All the other options presented are IMHO ugly hacks (one self admitted ;-)

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

(OK, @Joel's is not but assumes you can change the interface you are implementing)

(好吧,@Joel's 不是,但假设您可以更改正在实现的界面)

Just create an instance of the class with a getter for the result, it is clean and only requires you to implement the single class.

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