Java 为什么我没有得到NullPointerException?
我希望在以下程序的输出中出现Java 为什么我没有得到NullPointerException?,java,nullpointerexception,Java,Nullpointerexception,我希望在以下程序的输出中出现NullPointerException,因为在go方法中,c2为null。但它工作得很好,可以打印200。为什么? class CardBoard { Short story = 200; CardBoard go(CardBoard cb) { cb = null; return cb; } public static void main(String[] args) { CardBo
NullPointerException
,因为在go
方法中,c2
为null。但它工作得很好,可以打印200。为什么?
class CardBoard {
Short story = 200;
CardBoard go(CardBoard cb) {
cb = null;
return cb;
}
public static void main(String[] args) {
CardBoard c1 = new CardBoard();
CardBoard c2 = new CardBoard();
CardBoard c3 = c1.go(c2);
System.out.print(c2.story); // dout here
}
}
您将
go
函数的参数指向null,而不是c2
变量。go
方法可能会在执行过程中更改carboard
参数的内容(例如story
参数),但对象本身不会被“置空”。- 对c2的引用传递给go方法
- 该参考被指定给参数cb
- 方法代码为参数变量指定空值
c2
的引用的值被传递给go
方法,而不是引用本身。这样想吧。有4个内存插槽,其中3个包含指向在main
中创建的对象的值,分别命名为c1
、c2
和c3
,另一个内存插槽将保存传递到go
方法的值,命名为cb
。调用函数时,c2
中的值被复制到插槽cb
。然后,go
方法将值null
放入插槽cb
。但是,这不会更改插槽c2
中的值-它与方法调用之前保持相同。
假设r2
是对c2
的引用,假设123
是该引用的值。
因此,r2
“保持”123
,这只不过是c2的
位置
现在,当您调用
c1.go(c2)
时,将创建一个新的引用rN
,它保存123
,并传递给该方法。当您执行c2=null
时,引用rN
将变为null
,而不是c2
,要获得预期结果,请尝试使用
`System.out.print(cb.story);`
在置零后的go
方法中
cb
或
System.out.print(c3.story); // dout here
现在,在您的示例中,您将返回分配给c3
的null
。因此,您没有修改c2
变量
我对这些疑问的最好解释是
所有答案和注释都值得一读。在Java中,参数是通过值传递的,而不是通过引用传递的,因此您不是在修改变量
c2
,您只是“传递”了c2
指向的对象
如果您使用C#之类的语言,或许可以在java中实现这一点:
class CardBoard {
Short story = 200;
CardBoard go(byRef CardBoard cb) { // NOT REALLY ALLOWED, Compilation error
cb = null;
return cb;
}
public static void main(String[] args) {
CardBoard c1 = new CardBoard();
CardBoard c2 = new CardBoard();
CardBoard c3 = c1.go(byRef c2); // NOT REALLY ALLOWED, Compilation error
System.out.print(c2.story); // dout here
}
}
然后您将修改
c2
本身,但您唯一可以修改的是您传递的对象的内部状态(调用类似myObj.setSomething(x)
)。我认为您被引用和对象的工作方式误解了
主要功能
CardBoard c1 = new CardBoard();
c1 |100| Address ---points to---> Memory address at location 100
CardBoard c2 = new CardBoard();
c2 |400| Address ---points to---> Memory address at location 400
CardBoard c3 = c1.go(c2);
c3 |600| Address ---points to---> Memory address at location 600
System.out.print(c2.story); // dout here
围棋功能
CardBoard go(CardBoard cb) {
cb |400| Address ---points to---> Memory address at location 400
New cb reference is created which also points to memory location where c2 is pointing(Note, cb and c2 are two different reference but pointing to same memory location)
cb = null;
Above line changed cb reference to null, still c2 is pointing to same memory location.
return cb;
}
因此,当go函数返回时,c2没有变化
尝试更改cb引用上的story变量,您将看到它也会影响c2变量
cb是在不同的方法堆栈中创建的,然后c1、c2和c3是在不同的方法堆栈中创建的他可能还想到了
System.out.print(c3.story)
,它将抛出一个NPE,因为c3
将被分配null
。现在刚刚编辑了什么…?@akf:可能,他会在那里得到一个NPE。@user1612062:只是改进了问题,仅此而已。原来是这样的:)@Bohemian:哇,没想到我会犯那样的拼写错误。。谢谢你纠正我,我感到惭愧!