首先,我不确定如何表达这个问题,但我真的陷入困境(我读了这篇文章 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/