【问题标题】:Changing local variable from anonymous nested inner class从匿名嵌套内部类更改局部变量
【发布时间】:2018-10-29 23:24:15
【问题描述】:

我需要返回一个在methodB() 中设置的object,我已经尝试了很多并且也搜索了:

interface A{}
interface B{}

class Main{
  Object method(){
     Object o;

     new A(){
        methodA(){
            new B(){
                methodB(){
                    // how to use setters of o here?
                }
            }        
        }
    }

    return o;// o should contain the values set in methodB()
  }
}

我的实际代码

  public ImageUtil saveImagetoStorage() {
    final ImageUtil imageUtil[] = new ImageUtil[1];

    filepath.putFile(mPublishedImageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
        @Override
        public void onComplete(@NonNull final Task<UploadTask.TaskSnapshot> task) {

                UploadTask uploadTask = FirebaseUtil.sStorageReference.child(thumbs)
                        .child(randomName + ".jpg").putBytes(thumbData);

                uploadTask.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {

                        String downloadthumbUri = taskSnapshot.getDownloadUrl().toString();
                        imageUtil[0]=new ImageUtil();
                        imageUtil[0].setImgUrl(downloadUri);
                        imageUtil[0].setImgThumb(downloadthumbUri);
                    }
                });
        }
    });
    return imageUtil[0];
}

我错过了什么吗?提前致谢。

【问题讨论】:

  • methodA()methodB() 来自哪里?摘自 A 和 B ?还是接口?
  • 我认为o 需要最终确定:final Object o;
  • 正确的@azro,那些A和B是接口的实现。
  • o 可以是最终的,我们可以在 methodB() @markspace 中设置它,但是当我返回 o 时,它们将变为 null。
  • 您的saveImagetoStorage 方法在onSuccess 方法执行之前返回。此外,onSuccess 方法将由另一个线程执行,因此您的代码也需要成为线程安全的。重新考虑事件的顺序。您不能在下载完成之前返回ImageUtil,并且您不必等待UploadTask 任务完成。

标签: java inner-classes anonymous-inner-class


【解决方案1】:

免责声明:此答案是在将“实际代码”添加到问题之前编写的。

你不能,因为o 必须是有效最终的,无论你声明与否。

解决此问题的一种方法是将代码更改为

Object[] o = new Object[1];

new A() {
    methodA() {
        new B() {
            methodB() {
                o[0] = ...
            }
        }
    }
}

return o[0];

当然,除非您在到达 return o[0] 语句之前真正调用 methodB,否则这也行不通。

【讨论】:

【解决方案2】:

您的方法需要等待文件上传完成。

由于涉及到两个异步调用,一种方法是使用CompletableFuture

public ImageUtil saveImagetoStorage() {
    final CompletableFuture<ImageUtil> futureImageUtil = new CompletableFuture<>();

    filepath.putFile(mPublishedImageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
        @Override
        public void onComplete(@NonNull final Task<UploadTask.TaskSnapshot> task) {

            UploadTask uploadTask = FirebaseUtil.sStorageReference.child(thumbs)
                    .child(randomName + ".jpg").putBytes(thumbData);

            uploadTask.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {

                    String downloadthumbUri = taskSnapshot.getDownloadUrl().toString();
                    ImageUtil imageUtil = new ImageUtil();
                    imageUtil.setImgUrl(downloadUri);
                    imageUtil.setImgThumb(downloadthumbUri);
                    futureImageUtil.complete​(imageUtil); // Make imageUtil available
                }
            });
        }
    });
    return futureImageUtil.get(); // wait (potentially forever) until image available
}

您当然不应该假设异步操作会失败,因此您也需要添加失败处理程序,否则 get() 将永远等待,因为永远不会调用 complete​(...)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多