首页 > 解决方案 > 为什么 `break label` 不能在 lambda 表达式中使用?任何解决方法?

问题描述

我正在尝试使用 HTTPClient 库为 HTTP 请求实现重试机制。对于重试机制,我有一个要尝试的网站列表,我会尝试每个网站retries多次。当我收到status 200来自任何请求的 a 时,该过程结束。

我的想法是使用 booleanrequestSuccess和 label requestLabel。当我requestSuccess = true收到requestLabel一个status 200. 但是,变量必须是(effectively) final并且break标签在 lambda 表达式中不可用。

是否有任何解决方法来实现这种重试机制?

boolean requestSuccess = false;

requestLabel: 
for(String site: sites) {
    for(int i = 0; i < retries; i++) {
        client.request(site, data, requestOptions, (err, res, content) -> {
            if(err == null) {
                requestSuccess = true;
                break requestLabel;
            } else {
                log(...);
            }
        })
    }
}

if(!requestSuccess) {
    log("request failed");
}


一种可能的答案

受提交然后删除的答案的启发,我可以使用类似包装类的解决方案。我认为它会工作,但它似乎很脏?

boolean[] requestSuccess = new boolean[1];

requestLabel:
for(String site: sites) {
    for(int i = 0; i < retries; i++) {
        if(requestSuccess[0] == true) {
            break requestLabel;
        }

        client.request(site, data, requestOptions, (err, res, content) -> {
            if(err == null) {
                requestSuccess[0] = true;
            } else {
                log(...);
            }
        })
    }
}

if(!requestSuccess) {
    log("request failed");
}

标签: javaasynchronouslambdahttpclientnetty

解决方案


一个 lambda 在引擎盖下变成了它自己的类。就 java 解释器而言,就好像你有两个类。

class Main {
    public void runstuff() {
        labelX:
        for(...) {
            client.request(new Main$Foo().xyz(.....));
        }
    }

    class Foo {
         public xyz(....) {
             break labelX; // There is no labelX to break to here in Foo.xyz
         }
    }
}

推荐阅读