我查看了这段代码,但我不明白为什么这个程序会打印1
。
首先,在foo(myObject)
我们正在为最终分配一些东西,这怎么可能?
第二件事,在完成foo()
之后,我们会将myObject
设为null,那么我们怎样才能打印它?
public class MyClass {
private int myInt;
public static void foo(MyClass myObject) {
myObject.myInt = 1;
myObject = null;
}
public static void main(String[] args) {
final MyClass myObject = new MyClass();
myObject.myInt = 2;
foo(myObject);
System.out.println(myObject.myInt);
}
}
答案 0 :(得分:10)
首先,在
foo(myObject)
我们正在为final
分配内容,它是如何构成的?
对象不是final
,main
中的变量是final
。因此,在main
中,如果您在设置其值的初始行之后添加myObject = somethingElse;
,则无法编译,因为您无法在变量<中添加新值/ strong>即可。这对变量引用的对象是否可变是没有影响的。
第二件事,在
foo()
完成后,我们会让myObject
为空,那么我们怎样才能打印出来?
您的代码中有两个名为myObject
的单独的项:
main
foo
foo
中的代码将参数设置为null
,但这对main
中的变量没有任何影响。 (事实上,foo
不可能对main
中的变量产生任何影响; Java是一种纯粹的按值传递的语言。所有foo
都可以,正如您所演示的那样,使用传递给它的对象引用作为参数来修改变量和参数引用的对象的状态。)
让我们在foo
:
myObject.myInt = 1;
这是我们在记忆中所拥有的东西(遗漏了一些细节和无关紧要):
+−−−−−−−−−−−−−−−−−−−−−−+ | variable "myObject" | foo can change the +−−−−−−−−−−−−−−−−−−−−−−+ *state* of this foo can't change this−−>| Ref22458 |−−−+ | +−−−−−−−−−−−−−−−−−−−−−−+ | v | +−−−−−−−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−−+ +−−−>| object of type MyClass | | parameter "myObject" | | +−−−−−−−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−−+ | | myInt: 2 | foo can change this−−−−>| Ref22458 |−−−+ +−−−−−−−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−−+
......其中&#34; Ref22458&#34;只是指向您在main
中创建的对象的对象引用值的名称。
我们在foo
执行两行:
myObject.myInt = 1;
myObject = null;
我们在记忆中有这个:
+−−−−−−−−−−−−−−−−−−−−−−+ | variable "myObject" | foo can change the +−−−−−−−−−−−−−−−−−−−−−−+ *state* of this foo can't change this−−>| Ref22458 |−−−+ | +−−−−−−−−−−−−−−−−−−−−−−+ | v | +−−−−−−−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−−+ +−−−>| object of type MyClass | | parameter "myObject" | | +−−−−−−−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−−+ | | myInt: 1 | foo can change this−−−−>| null |−−−+ +−−−−−−−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−−+
请注意foo
如何更改对象的状态(myInt
现在为1
),并且可以更改参数中的值 {{1 (它现在是myObject
),但无法更改变量 null
中的值(原因有两个:它无法访问变量[Java是按值传递],变量是myObject
)。
答案 1 :(得分:0)
Java不是通过引用传递的(引用是按值传递的),将myObject
分配给null
并没有什么不同。它不是final
,因为它不是foo()
方法中的最终版本。它打印1,因为您将myObject
的引用传递给foo()
并设置其字段。它仍然是一个可变对象,所以它的值会更新。
答案 2 :(得分:0)
final
只是指定对象本身不应该更改 - 当与代码类一起使用时,它只会阻止某人执行myObject = ...
。除非您将MyClass.myInt
标记为final,否则即使在赋值后,您也可以将任何值分配给所需的int。
解决此问题的方法是将myInt
设为私有,并为其提供公共getter,防止其被修改(反射除外)