java - 如何使方法最终变量在输入 lambda 时不改变

标签 java codenameone

首先,我不确定如何表达这个问题,但我真的陷入困境(我读了这篇文章 Why can I still make changes to this final variable? 但它没有帮助)。我使用 CodenameOne 框架,但我也不确定问题是从它那里爆发出来的,它可能是一般的 java。

在我的应用程序中,我正在将报告发送到服务器。效果很好。

Report类中方法如下:

    public void sendAsync(SuccessCallback<Report> onSuccess) {
      // Update : With a shallow copy it does not work
     // final Report currentReport = this;

     // But with a deeper copy it does
     final Report currentReport = clone(this);

     final MultipartRequest request = new MultipartRequest() {

        @Override
        protected void readResponse(InputStream input) throws IOException { 
        // ... Does stuff here on Report's attributes

        // Here the variable currentReport changes during overlapping sendings

      @Override
      postResponse(){

        // The goal is to use some attributes from the current report
        // to be shown in a popup to remind the user what we sent
        // BUT the as written above the currentReport changes during 
        // overlapping sendings so that what is shown to the user only 
        // deals with the lastest report and does not make sense.

        onSuccess(currentReport);

      }


     }
    } // end of sendAsync

当用户按下发送按钮时,我这样调用它:

 Report myReport = new Report();
 myReport.photoPath.set(...);
 myReport.id.set(...);
 anotherMethod(myReport); // this passes myReport to sendAsync but never modifies it  
 // Here myReport has still the right attributes based on the parameters
 myReport.sendAsync((sentReport) -> {/* does something else */});

问题是,当用户在上一次发送正在进行时按下发送按钮时,上一次发送会采用下一个发送的属性,而这不是我想要的。

所以我不知道在代码中在哪里搜索,变量不是静态的。当发送重叠时如何使先前的currentReport不改变?

2018 年 2 月 25 日更新

我不明白的是为什么我必须创建 this 的深拷贝才能使其工作(static Report clone(Report sourceReport) 方法创建一个新报表,使用传入的 sourceReport 的属性设置其属性,并返回创建的报表)?

此外,当用户按下按钮时,将完成以下操作:

 Report report = new Report();
 report.photoPath.set(the_path_returned_from_the_camera);
 report.otherAttributes.set(values);

 report.sendAsync((sentReport) -> {

     showConfirmationPopup(sentReport);

     // However here report.photoPath returns a different path
     // from sentReport.photoPath which surprises me. Why do they differ ?

     System.out.println(report.photoPath.get()); //prints /home/a.jpg
     System.out.println(sentReport.photoPath.get()); //prints /home/b.jpg

  });

我也不明白的是,为什么在 lambda 中,report 和 sendReport 在完成深复制时没有相同的内容(浅复制也有相同的内容)?

报表构造函数的工作方式如下:

 public Report() {
    this.location.set(null);
    this.photoPath.set("");  
     ...
    this.connectionError = false;
}

提前非常感谢您,如果需要,我可以提供更多详细信息

最佳答案

在Java中。没有内置方法来识别哪个方法修改对象或不修改对象,因此无法阻止这些方法(例如:没有相当于 C++“const 方法”的方法)。但是,根据具体情况,有一些设计模式可以实现您想要做的事情。

Immutable :简单地创建一个没有setter的对象,这样它在创建后就无法修改;然而,引用仍然可以更改(除非最终)。

Memento (至少的变体):基本上在事件触发时拍摄对象的快照/副本,因此在事件触发后对原始对象所做的任何修改都不会影响已触发事件的修改。但要小心,您可能需要某种“深度克隆”,如果您的对象包含任何其他对象, doint obj1 = obj2 只会使两个引用仍然可以修改的同一实例。

围绕您的问题的另一个选择可能只是阻止事件重新提交,直到上一个事件完成(成功或出现异常/失败)。

关于java - 如何使方法最终变量在输入 lambda 时不改变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48962336/

相关文章:

java - 将最终变量传递给 MouseListener 方法并返回结果

java - 如何在代号一的路径上正确书写文本

java - 使用 nativeInterface 创建屏保

c# - 在模块 CommonLanguageRuntimeLibrary 中找不到类型 System.ApplicationException

java - 如何在 JLabel 或 java 中显示 🔴

java - 我应该将 IDL 文件和生成的代码放在 Maven 项目中的哪里?

java - 如何使用 Jackson JSON 反序列化枚举列表?

java - CAS 单点退出回调命中 403(forbidden)

java - 包 java.util.regex 不存在(代号one)

java - 手动缓存 Rest 而不检查 ETag 和 Last-Modified 的 header