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

从内部类引用的JAVA局部变量必须是final或有效final,java,Java,我试图返回stats对象 但是我越来越 从内部类引用的局部变量必须是final或final 有效最终 在stats=statistics上如何返回对象,但要确保.close()是否正在运行 public static Statistics getStatistics(String environmentName) { Container container = getContainer(environmentName); Statistics stats = new Stati

我试图返回
stats
对象

但是我越来越

从内部类引用的局部变量必须是final或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;
}
publicstaticstatistics getStatistics(stringenvironmentname){
Container Container=getContainer(environmentName);
统计数据=新统计数据();
试一试{
dockerClient().statsCmd(container.getId()).exec(新的ResultCallback()){
@凌驾
公共void onStart(可关闭可关闭){
}
@凌驾
public void onNext(统计){
统计数据=统计数据;
}
@凌驾
公共作废登记员(可丢弃){
}
@凌驾
未完成的公共空间(){
}
@凌驾
public void close()引发IOException{
}
}).close();
}捕获(IOE异常){
e、 printStackTrace();
}
返回统计;
}

您正在创建一个巨大的内部类:

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();
new ResultCallback(){@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()抛出IOException{}).close();
问题是,您在方法中定义的统计信息是不必要的,因为您在匿名内部类
@Override public void onNext(Statistics Statistics){stats=Statistics;}


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

您想调用
getStatistics
并立即使用生成的统计信息。这称为同步使用

但实际上,回调只能异步地通知用户统计信息最终到达

因此,改变:

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

f(字符串环境){
检索统计(env);
}
公共静态void retrieveStatistics(字符串环境名称){
Container Container=getContainer(environmentName);
stats=null;
试一试{
dockerClient().statsCmd(container.getId()).exec(新的ResultCallback()){
统计数据;
@凌驾
public void onNext(统计){
g(统计);
stats=statistics;//改用onComplete时的替代方法。
}
@重写公共void onStart(Closeable Closeable){}
@重写公共无效onError(可丢弃可丢弃){}
@重写公共void onComplete(){
g(stats);//或者这个
}
@重写公共void close()引发IOException{}
}).close();
}捕获(IOE异常){
e、 printStackTrace();
}
}

您所做的繁忙等待循环并不理想。

您可以尝试使用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);
    }
}
publicstaticstatistics getStatistics(stringenvironmentname){
Container=null;
CompletableFuture=新的CompletableFuture();
试一试{
dockerClient().statsCmd(container.getId()).exec(新的ResultCallback()){
@凌驾
公共void onStart(可关闭可关闭){
}
@凌驾
public void onNext(统计){
如果(!future.isDone()){
未来。完成(统计);
}
}
@凌驾
公共作废登记员(可丢弃){
未来。完全例外(可丢弃);
}
@凌驾
未完成的公共空间(){
如果(!future.isDone()){
future.complete(空);
}
}
@凌驾
public void close()引发IOException{
}
}).close();
}捕获(IOE异常){
e、 printStackTrace();
}
试一试{
//等待统计数据解决
返回future.get();
}捕获(例外e){
抛出新的RuntimeException(e.getMessage(),e);
}
}

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

。本地内部类可以访问包含它的类的字段以及它在其中定义的块的字段。然而,这些类只有在声明为final或实际上是final时才能访问包含它的块的变量或参数。@Brijesh用简单的英语来说这是什么意思?如果我把
统计数据
说我不能给final赋值…@sadas根据它看起来像
exec()
方法正在返回某些内容,很可能是作为参数传递的对象。创建一个将结果存储在字段中的普通类。稍后,您可以从
exec()调用的返回对象访问该字段。
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);
    }
}