为什么我没有得到NullPointerException?

时间:2013-07-27 05:00:17

标签: java nullpointerexception

我希望以下程序的输出中有NullPointerException,因为在go方法中,c2已为空。但它工作正常并打印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
    }
}

7 个答案:

答案 0 :(得分:1)

您将go函数的参数指向null,而不是c2变量。 go方法可能会在其执行中更改CardBoard参数的内容(例如story参数),但对象本身不会被“取消”。

答案 1 :(得分:1)

Java使用pass by value semantics进行方法调用。这意味着对c2的引用值传递给go方法,而不是引用本身。这样想吧。有4个内存插槽,其中3个包含指向main中创建的对象的值,分别命名为c1c2c3,另一个将保存传递到名为go的{​​{1}}方法的值。调用该函数时,cb中的值将复制到插槽c2。然后cb方法将值go放入广告位null。但是,这不会更改插槽cb中的值 - 它仍然与方法调用之前的值相同。

答案 2 :(得分:1)

Is Java pass-by-value?

让我们说r2c2的引用,让我们说123是该引用的值。 所以r2“拥有”123,这只是c2's位置。

现在,当您致电c1.go(c2)时,会创建一个新的引用rN,其中包含123,并传递给该方法。当您执行c2 = null时,参考rN变为null而不是c2

答案 3 :(得分:1)

在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)之类的东西)。

答案 4 :(得分:0)

  • 引用到c2将传递给go方法。
  • 将参考分配给参数cb
  • 方法代码为参数变量
  • 分配null

所有这些对go方法之外的c2变量的内容没有影响

答案 5 :(得分:0)

要获得预期结果,请尝试使用

`System.out.print(cb.story);`
go cb 之后的nulling方法内

System.out.print(c3.story); // dout here

现在,在您的情况下,您将返回分配给null的{​​{1}}。所以你没有修改c3变量。

我发现关于这些疑虑的最佳解释是here

所有答案和评论都值得一读。

答案 6 :(得分:0)

我认为您被参考和对象的工作方式误解了

主要功能

  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引用上更改故事变量,您将看到它也影响到c2变量。

cb在不同的方法堆栈中创建,然后创建c1,c2和c3