-4

我希望NullPointerException在以下程序的输出中出现 a,因为在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
    }
}
4

7 回答 7

1

Java 是按值传递吗?.

可以说r2是对 的引用c2,可以说123是该引用的值。所以r2“持有”123这不过是c2's位置。

现在,当您调用 时c1.go(c2),将创建一个新引用,该引用rN保存123并传递给该方法。而当你这样做c2 = null的时候,它会rN变成null而不是参照c2

于 2013-07-27T05:15:24.950 回答
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))。

于 2013-07-27T05:17:00.063 回答
1

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

于 2013-07-27T05:01:53.730 回答
1

Java对方法调用使用按值传递语义。这意味着将引用的值c2传递给go方法,而不是引用本身。这样想吧。有 4 个内存槽,其中 3 个包含指向在 中创建的对象的值main,它们分别命名为c1c2c3,另一个用于保存传递给go方法的值,命名为cb。当函数被调用时,值 inc2被复制到 slotcb中。然后该go方法将值null放入 slot 中cb。但是,这不会改变 slot 中的值c2——它与方法调用之前的值相同。

于 2013-07-27T05:11:14.200 回答
0

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

`System.out.print(cb.story);`

在cbgo之后的方法里面。nulling

或者

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

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

我找到的关于这些疑问的最佳解释是here

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

于 2013-07-27T05:15:32.380 回答
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

于 2013-07-27T05:17:30.950 回答
0
  • 对 c2的引用被传递给 go 方法。
  • 引用分配给参数 cb
  • 方法代码将 null 分配给参数变量

这一切对go方法外的c2变量的内容没有影响

于 2013-07-27T05:10:11.727 回答