为什么这不是抛出一个NullPointerException?

需要澄清以下代码:

StringBuilder sample = new StringBuilder(); StringBuilder referToSample = sample; referToSample.append("B"); System.out.println(sample); 

这将打印B以便certificatesamplereferToSample对象引用相同的内存引用。

 StringBuilder sample = new StringBuilder(); StringBuilder referToSample = sample; sample.append("A"); referToSample.append("B"); System.out.println(referToSample); 

这将打印AB也certificate相同。

 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()给出的奇怪的hex表示,但是这取决于实现。 1

 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显示了取消引用sample不会将sample的引用中断到StringBuilder在00012345

1 GC的考虑使得这个不合理。

最初,正如你所说的,参考sample是指如下所示的sample

1.情景1:

参考样本是指样本

2.情景1(续):

referToSample.append( “B”)

  • 在这里作为参考sample是指sample ,所以它附加“B”,而你写

    referToSample.append("B")

情景2中发生同样的事情

但是,情况3:如六分法所说,

当你指定null指向referToSample时候,它并没有改变数值,而只是打断了sample引用 ,现在它指向没有了 。 如下所示:

当referToSample = null时

现在,当referToSample指向无处 ,所以当你referToSample.append("A"); 它不会有任何值或引用它可以附加A.所以,它会抛出NullPointerException

但是sample与您初始化的sample相同

StringBuilder sample = new StringBuilder(); 所以它已经被初始化了,所以现在它可以附加A,并且不会抛出NullPointerException

简而言之:您将null分配给引用variables,而不是分配给对象。

在一个示例中,您可以更改由两个引用variables引用的对象的状态 。 发生这种情况时,两个参考variables都会反映这个变化。

在另一个例子中,你改变了分配给一个variables的引用,但是这对对象本身没有影响,所以仍然引用原始对象的第二个variables不会注意到对象状态的任何变化。


至于你的具体“规则”:

如果两个对象引用相同的对象,那么如果我们改变任何值,那么它也将反映到其他的,因为它们都指向相同的内存引用。

再次提到改变两个variables引用的一个对象的状态

那么为什么这个规则不适用于这里? 如果我将null指派给referToSample,那么sample也应该是null,它应该抛出nullPointerException,但不是抛出,为什么?

再一次,你改变了一个variables的引用 ,这个variables对另一个variables的引用完全没有影响

这是两个完全不同的行动,将导致两个完全不同的结果。

看到这个简单的图表:

图

当你在referToSample上调用方法时, [your object]被更新,所以它也会影响sample 。 但是当你说referToSample = null ,你只需要改变referToSample 引用的东西。

这里的'sample'和'referToSample'是引用同一个对象。也就是不同指针访问同一个内存位置的概念。 因此,将一个引用variables赋值为null不会破坏该对象。

  referToSample = null; 

意味着只有指向null的“referToSample”,对象保持不变,其他引用variables正常工作。 所以对于没有指向null并且有一个有效对象的'sample'

  sample.append("A"); 

工作正常。 但是,如果我们尝试将null追加到“referToSample”,它将显示NullPointException。 那是,

  referToSample .append("A");-------> NullPointerException 

这就是为什么你的第三个代码片段中有NullPointerException。

每当使用一个新的关键字时,它在堆上创build一个对象

1)StringBuilder sample = new StringBuilder();

2) StringBuilder referToSample = sample;

在2)referenceSamples是在同一个对象样本上创build的

因此referToSample = null; 是空值只有参考样本参考不会影响样本这就是为什么你没有得到NULL指针exception感谢Java的垃圾收集

简单来说,Java没有引用,它只是通过对象引用。