Java 为什么这个程序输出1?
我看过这段代码,不明白为什么这个程序会打印Java 为什么这个程序输出1?,java,oop,Java,Oop,我看过这段代码,不明白为什么这个程序会打印1 首先,在foo(myObject)中,我们给final赋值,这怎么可能呢 第二件事,在foo()完成后,我们将myObject设置为null,那么我们如何打印它呢 public class MyClass { private int myInt; public static void foo(MyClass myObject) { myObject.myInt = 1; myObject = null;
1
首先,在foo(myObject)
中,我们给final赋值,这怎么可能呢
第二件事,在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);
}
}
Java不是按引用传递的(引用是按值传递的),将
myObject
赋值给null
并没有什么区别。它不是final
也不是,因为在foo()方法中它不是final。它打印1,因为您将myObject
的引用传递到foo()
并设置其字段。它仍然是一个可变对象,因此其值会更新
首先,在foo(myObject)
中,我们给final
分配了一些东西,这怎么可能呢
对象不是final
,main
中的变量是final
。因此,在main
中,如果您添加了myObject=somethingElse
在设置其值的初始行之后,它将不会编译,因为您不能在变量中放入新值。这对变量引用的对象是否可变没有影响
第二件事,在foo()
完成后,我们将myObject
设置为null,那么我们如何打印它呢
在您的代码中有两个独立的东西称为myObject
:
main
foo
foo
中的代码将参数设置为null
,但这对main
中的变量没有任何影响。(事实上,foo
不可能对main
中的变量产生任何影响;Java是一种纯粹的传递值语言。正如您所演示的,foo
所能做的,就是修改变量和参数引用的对象的状态,使用传递给它的对象引用作为参数。)
让我们在foo
中的这一行之前停止代码:
myObject.myInt = 1;
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 |−−−+ +−−−−−−−−−−−−−−−−−−−−−−−−+
+−−−−−−−−−−−−−−−−−−−−−−+
+−−−−−−−−−−−−−−−−−−−−−−+
|变量“myObject”| foo可以更改
+−−−−−−−−−−−−−−−−−−−−−−+ *本州*
福改变不了这个−−>| 参考文献22458|−−−+ |
+−−−−−−−−−−−−−−−−−−−−−−+ | v
| +−−−−−−−−−−−−−−−−−−−−−−−−+
+−−−−−−−−−−−−−−−−−−−−−−+ +−−−>| MyClass类型的对象|
|参数“myObject”||+−−−−−−−−−−−−−−−−−−−−−−−−+
+−−−−−−−−−−−−−−−−−−−−−−+ | | myInt:1|
福可以改变这一点−−−−>| 空的|−−−+ +−−−−−−−−−−−−−−−−−−−−−−−−+
+−−−−−−−−−−−−−−−−−−−−−−+
注意foo
如何更改对象的状态(myInt
现在是1
),如何更改参数myObject
(现在是null
)中的值,但无法更改变量myObject
中的值(原因有两个:它无法访问变量[Java是按值传递的],变量是final
)。final
只是指定对象本身不应更改-当与代码这样的类一起使用时,它只是阻止某人执行myObject=…
。除非您标记了MyClass.myInt
final,否则即使在赋值之后,您也可以为int赋值
解决这个问题的方法是将myInt
设为私有,并为其提供一个公共getter,防止它被修改(反射除外),因为myObject.myInt=1
。你以为会是什么?@bradimus没那么简单。。。在print语句之前,对象被设置为null,这可能会给那些不熟悉Java的人带来混乱。你知道Java是如何将对象传递给其他方法的吗???@MatthewDiana,你是对的,那里存在潜在的混乱,所以我想你可能会更小心使用你的语言。设置为null的不是对象,而是对它的一个引用。但是myObject=null的可能重复出现在foo()的内部,这不是对final的一个辅助吗?@limitless否。这些是不同范围内的不同引用。@limitless仅适用于foo()
的范围内。您没有设置在main
中声明为final的myObject
,而是为foo
方法设置参数myObject
。
+−−−−−−−−−−−−−−−−−−−−−−+
| 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 |−−−+ +−−−−−−−−−−−−−−−−−−−−−−−−+
+−−−−−−−−−−−−−−−−−−−−−−+