为什么这不会抛出NullPointerException?
需要澄清以下代码:
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample.append("B");
System.out.println(sample);
这将打印B
以便证明sample
和referToSample
对象引用相同的内存引用。
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
sample.append("A");
referToSample.append("B");
System.out.println(referToSample);
这将打印AB
也证明相同。
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
referToSample.append("A");
System.out.println(sample);
显然这将抛出NullPointerException
因为我试图在空引用上调用append
。
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
sample.append("A");
System.out.println(sample);
所以这里是我的问题,为什么最后一个代码示例不抛出NullPointerException
因为我从前面两个示例中看到并理解的是,如果两个对象引用同一对象,那么如果我们更改任何值,那么它也会反映到其他对象,因为它们都指向到相同的内存参考。 那么为什么这条规则不适用于此? 如果我将null
指派给referToSample,那么sample也应该为null,它应该抛出一个NullPointerException,但它不会抛出一个,为什么?
null
分配不会通过全局销毁该对象来更改值。 这种行为会导致难以跟踪的错误和违反直觉的行为。 他们只是打破了具体的参考。
为了简单起见,我们假设sample
指向地址12345.这可能不是地址,并且仅用于使事情变得简单。 该地址通常用Object#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);
从标有See diagram
的线条See diagram
,当时的对象图如下:
图1:
[StringBuilder sample] -----------------> [java.lang.StringBuilder@00012345]
↑
[StringBuilder referToSample] ------------------------/
图2:
[StringBuilder sample] -----------------> [java.lang.StringBuilder@00012345]
[StringBuilder referToSample] ---->> [null pointer]
图2示出了废止referToSample
不破裂的参考sample
在到StringBuilder 00012345
。
1GC的考虑使这种情况令人难以置信。
最初,它是如你所说referToSample
指的是sample
,如下图所示:
1.情景1:
2.情景1(续):
这里referToSample
指的是sample
,所以追加“B”,而你写
referToSample.append("B")
情景2中发生同样的事情:
但是,情况3:如六分法所说,
当你将null
到referToSample
当它是指sample
并没有改变值 ,而不是它只是打破了从参考 sample
,而现在它指向无处。 如下所示:
现在,因为referToSample
指向任何地方,所以当你referToSample.append("A");
它不会有任何值或引用,它可以附加A.因此,它会抛出NullPointerException
。
但是sample
与您初始化的sample
相同
StringBuilder sample = new StringBuilder();
所以它已经被初始化了,所以现在它可以附加A,并且不会抛出NullPointerException
简而言之:您将null分配给引用变量,而不是分配给对象。
在一个示例中,您可以更改由两个引用变量引用的对象的状态。 发生这种情况时,两个参考变量都会反映变化。
在另一个例子中,你改变了分配给一个变量的引用,但是这对对象本身没有影响,所以仍然引用原始对象的第二个变量不会注意到对象状态的任何变化。
至于你的具体“规则”:
如果两个对象引用同一个对象,那么如果我们改变任何值,那么它也会反映到其他对象,因为它们都指向相同的内存引用。
再次提到改变两个变量引用的一个对象的状态。
那么为什么这条规则不适用于此? 如果我将null指派给referToSample,那么sample也应该为null,它应该抛出nullPointerException,但它不会抛出,为什么?
再一次,你改变了一个变量的引用,它对另一个变量的引用完全没有影响。
这是两个完全不同的行为,会导致两个完全不同的结果。
链接地址: http://www.djcxy.com/p/76217.html