继Michel的帖子之后,我自己制作了另一个例子来解释它。希望能有所帮助。
public static void main(String[] args){
MyParam myParam = thisIsWhy(new MyObj());
myParam.setArgNewName();
System.out.println(myParam.showObjName());
}
public static MyParam thisIsWhy(final MyObj obj){
MyParam myParam = new MyParam() {
@Override
public void setArgNewName() {
obj.name = "afterSet";
}
@Override
public String showObjName(){
return obj.name;
}
};
return myParam;
}
public static class MyObj{
String name = "beforeSet";
public MyObj() {
}
}
public abstract static class MyParam{
public abstract void setArgNewName();
public abstract String showObjName();
}
从上面的代码中,在方法
thisIsWhy()中,我们实际上
没有将[argument MyObj obj]分配给MyParam中的一个
真实引用。相反,我们只是在MyParam内部的方法中使用
[argument MyObj obj]。
但是,在完成方法
thisIsWhy()之后,
参数(对象)MyObj是否仍然存在?
看起来应该存在,因为我们可以在主函数中看到我们仍然调用了方法
showObjName(),并且它需要访问
obj。即使方法已经返回,MyParam仍将使用/访问方法参数!
Java如何实现这一点是生成一个
argument MyObj obj的副本,也是MyParam对象中的一个隐藏引用(但它不是MyParam中的正式字段,因此我们看不到它)。
当我们调用“showObjName”时,它将使用该引用获取相应的值。
但是,如果我们没有将参数设置为final,则会导致我们可以将新的内存(对象)重新分配给
argument MyObj obj,从而产生一种情况。
从技术上讲,根本没有冲突! 如果我们被允许这样做,下面将是情况:
- 现在我们有一个隐藏的 [MyObj obj] 指向一个 [Memory A in heap],现在在 MyParam 对象中。
- 我们还有另一个 [MyObj obj],它是参数指向一个 [Memory B in heap],现在在 thisIsWhy 方法中。
没有冲突,但“令人困惑!” 因为它们都使用相同的“引用名称”,即“obj”。
为了避免这种情况,将其设置为“final”以避免程序员编写“容易出错”的代码。
int foo(int* bar)
,最后一个是int foo(int* &bar)
。后者是通过引用传递指针,前者是通过值传递引用。 - jerslan