com*_*mit 89 java reference nullpointerexception
以下代码的澄清说明:
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample.append("B");
System.out.println(sample);
Run Code Online (Sandbox Code Playgroud)
这将打印,B
以便证明sample
和referToSample
对象引用相同的内存引用.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
sample.append("A");
referToSample.append("B");
System.out.println(referToSample);
Run Code Online (Sandbox Code Playgroud)
这将打印AB
,也证明是相同的.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
referToSample.append("A");
System.out.println(sample);
Run Code Online (Sandbox Code Playgroud)
显然这将抛出NullPointerException
因为我试图调用append
null引用.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
sample.append("A");
System.out.println(sample);
Run Code Online (Sandbox Code Playgroud)
所以这是我的问题,为什么最后一个代码示例没有抛出,NullPointerException
因为我从前两个示例中看到并理解的是,如果两个对象引用同一个对象,那么如果我们更改任何值,那么它也会反映到其他,因为它们都指向相同的内存参考.那么为什么这条规则不适用于此?如果我分配null
给referToSample,那么sample也应该为null,它应该抛出一个NullPointerException,但它不会抛出一个,为什么?
ζ--*_*ζ-- 89
null
赋值不会通过全局销毁该对象来更改值.这种行为会导致难以追踪的错误和违反直觉的行为.他们只打破那个特定的参考.
为简单起见,我们假设sample
指向地址12345.这可能不是地址,仅用于简化此处.地址通常用给定的奇怪十六进制表示1Object#hashCode()
,但这是依赖于实现的.
StringBuilder sample = new StringBuilder(); //sample refers to
//StringBuilder at 12345
StringBuilder referToSample = sample; //referToSample refers to
//the same StringBuilder at 12345
//SEE DIAGRAM 1
referToSample = null; //referToSample NOW refers to 00000,
//so accessing it will throw a NPE.
//The other reference is not affected.
//SEE DIAGRAM 2
sample.append("A"); //sample STILL refers to the same StringBuilder at 12345
System.out.println(sample);
Run Code Online (Sandbox Code Playgroud)
从标See diagram
有当时物体图的线条如下:
图1:
[StringBuilder sample] -----------------> [java.lang.StringBuilder@00012345]
?
[StringBuilder referToSample] ------------------------/
Run Code Online (Sandbox Code Playgroud)
图2:
[StringBuilder sample] -----------------> [java.lang.StringBuilder@00012345]
[StringBuilder referToSample] ---->> [null pointer]
Run Code Online (Sandbox Code Playgroud)
图2显示,取消referToSample
不会破坏sample
StringBuilder 的引用00012345
.
1 GC的考虑因素使这一点难以置信.
Par*_*rth 62
最初,它是如你所说referToSample
指的是sample
如下图所示:
1.场景1:
2.情景1(续):
在这里referToSample
指的是sample
,所以在你写的时候附加了"B"
referToSample.append("B")
Scenario2中发生了同样的事情:
但是,在 3.场景3中:正如hexafraction所说,
当你将null
要referToSample
当它是指sample
它并没有改变价值,而不是它只是打破了参考的sample
,而现在它指向无处.如下所示:
现在,因为没有referToSample
点,所以当你没有任何值或参考它可以追加A.所以,它会抛出.referToSample.append("A");
NullPointerException
但sample
仍然与你初始化它一样
StringBuilder sample = new StringBuilder();
所以它已被初始化,所以现在它可以附加A,而不会抛出 NullPointerException
Hov*_*els 17
简而言之:您将null赋给引用变量,而不是对象.
在一个示例中,您可以更改由两个引用变量引用的对象的状态.发生这种情况时,两个参考变量都将反映变化.
在另一个示例中,您更改分配给一个变量的引用,但这对对象本身没有影响,因此仍然引用原始对象的第二个变量将不会注意到对象状态的任何更改.
至于你的具体"规则":
如果两个对象引用同一个对象,那么如果我们更改任何值,那么它也会反映到其他对象,因为它们都指向相同的内存引用.
同样,您指的是更改两个变量引用的一个对象的状态.
那么为什么这条规则不适用于此?如果我为referToSample分配null,那么sample也应该为null并且它应该抛出nullPointerException但是它没有抛出,为什么?
同样,你改变参考具有绝对的一个变量没有影响对参考其他变量.
这是两个完全不同的动作,将导致两个完全不同的结果.
看到这个简单的图表:
当你调用一个方法上referToSample
,然后[your object]
进行更新,所以它影响sample
了.但是,当你说referToSample = null
,那么你只需更改什么referToSample
是指到.