从内部类引用的JAVA局部变量必须是最终的或有效的最终

时间:2018-01-03 12:57:18

标签: java

我正在尝试返回stats对象。

但我得到了

  

从内部类引用的局部变量必须是final或   有效的最终

stats = statistics;上的

如何返回对象,但确保运行.close();

 public static Statistics getStatistics(String environmentName) {
    Container container = getContainer(environmentName);
    Statistics stats = new Statistics();

    try {
        dockerClient().statsCmd(container.getId()).exec(new ResultCallback<Statistics>() {
            @Override
            public void onStart(Closeable closeable) {

            }

            @Override
            public void onNext(Statistics statistics) {
                stats = statistics;
            }

            @Override
            public void onError(Throwable throwable) {

            }

            @Override
            public void onComplete() {

            }

            @Override
            public void close() throws IOException {

            }
        }).close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return stats;
}

3 个答案:

答案 0 :(得分:0)

你正在创造一个无法形成的内部阶级:

new ResultCallback<Statistics>() { @Override public void onStart(Closeable closeable) { } @Override public void onNext(Statistics statistics) { stats = statistics; } @Override public void onError(Throwable throwable) { } @Override public void onComplete() { } @Override public void close() throws IOException { } }).close();

问题是你在方法中定义了不必要的统计数据,因为你在匿名内部类@Override public void onNext(Statistics statistics) { stats = statistics; }中再次定义它

相反,尝试直接在类中声明变量并初始化为null。内部函数只在匿名类中重新定义它。

答案 1 :(得分:0)

您想要致电getStatistics并立即使用生成的统计信息。这称为 synchrone 用法。

但实际上只有异步才会被回调通知统计数据最终到达。

所以改变:

f(String env) {
    Statistics stats = getStatistics(env);
    g(stats);
}

f(String env) {
    retrievStatistics(env);
}

public static void retrieveStatistics(String environmentName) {
    Container container = getContainer(environmentName);
    stats = null;
    try {
        dockerClient().statsCmd(container.getId()).exec(new ResultCallback<Statistics>() {
            Statistics stats;

            @Override
            public void onNext(Statistics statistics) {
                g(statistics);
                stats = statistics; // Alternative when using onComplete instead.
            }

            @Override public void onStart(Closeable closeable) {}
            @Override public void onError(Throwable throwable) { }
            @Override public void onComplete() {
                g(stats); // Or this
            }
            @Override public void close() throws IOException { }
        }).close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

像你一样忙碌的等待循环是不理想的。

答案 2 :(得分:0)

您可以尝试使用java.util.concurrent.CompletableFuture(java 8)。 在这种情况下:

public static Statistics getStatistics(String environmentName) {
    Container container = null;
    CompletableFuture<Statistics> future = new CompletableFuture<>();

    try {
        dockerClient().statsCmd(container.getId()).exec(new ResultCallback<Statistics>() {
            @Override
            public void onStart(Closeable closeable) {

            }

            @Override
            public void onNext(Statistics statistics) {
                if (!future.isDone()) {
                    future.complete(statistics);
                }
            }

            @Override
            public void onError(Throwable throwable) {
                future.completeExceptionally(throwable);
            }

            @Override
            public void onComplete() {
                if (!future.isDone()) {
                    future.complete(null);
                }
            }

            @Override
            public void close() throws IOException {

            }
        }).close();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        // wait until statistics resolved
        return future.get();

    } catch (Exception e) {
        throw new RuntimeException(e.getMessage(), e);
    }
}

或者,如果exec代码是同步的,则可以使用AtomicReference作为临时容器。该方法类似于上面的CompletableFuture示例,但开销较小