Java 在匿名內部函式中為外部函式變數賦值的解決方案
阿新 • • 發佈:2019-02-04
新人一枚,請多包涵。
Java匿名內部函式本人不怎麼主動使用,但是經常會呼叫一些API,其中會呼叫一些介面,而這些介面是需要使用匿名內部類來實現的,於是就遇到了一些問題。
就比如okHttp3 的介面呼叫
OkHttpClient okHttpClient = new OkHttpClient(); final Request okRequest = new Request.Builder() .url(url) .build(); Call call = okHttpClient.newCall(okRequest); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException {});
就要使用匿名內部類。
這一用不要緊,一個問題卻難到了我,由於需要寫一個微信登陸的Controller,需要從微信端獲取使用者的js_code再由伺服器向微信伺服器傳送data以換取使用者的openId以及sessionKey,於是就想到了okhttp3。
由於內部類的機制,內部類在使用外部類的成員變數時,該變數必須是final修飾的,至於理由,我覺得這個部落格寫的很生動:點選開啟連結。因此,如果想在內部類直接為外部類變數賦值的話是不可行的。那麼我如何在外部類得到我在匿名內部類中獲取取的openId呢?
【解決方案】
public Map<String,Object> loginWithWechat(HttpServletRequest request){ String loginUrl = "https://api.weixin.qq.com/sns/jscode2session?appid="+APP_ID +"&secret=" + SECRET + "&js_code=" + jsCode + "&grant_type=authorization_code"; OkHttpClient okHttpClient = new OkHttpClient(); final Request okRequest = new Request.Builder() .url(loginUrl) .build(); Call call = okHttpClient.newCall(okRequest); final Map<String, Object> resultMap = new HashMap<>(); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { String jsonRes = response.body().string(); resultMap.put("json",jsonRes); } }); String jsonStr = resultMap.get("json"); }
【個人總結】
不只是Map,物件也可以通過get() set()方法獲取匿名內部函式的變數。原來,雖然final不能改變變數地址,但是可以改變物件的成員變數,看來還是對Java final的修飾不熟悉啊。