Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么我没有得到NullPointerException?_Java_Nullpointerexception - Fatal编程技术网

Java 为什么我没有得到NullPointerException?

Java 为什么我没有得到NullPointerException?,java,nullpointerexception,Java,Nullpointerexception,我希望在以下程序的输出中出现NullPointerException,因为在go方法中,c2为null。但它工作得很好,可以打印200。为什么? class CardBoard { Short story = 200; CardBoard go(CardBoard cb) { cb = null; return cb; } public static void main(String[] args) { CardBo

我希望在以下程序的输出中出现
NullPointerException
,因为在
go
方法中,
c2
为null。但它工作得很好,可以打印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
    }
}

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

  • 对c2的引用传递给go方法
  • 该参考被指定给参数cb
  • 方法代码为参数变量指定空值
所有这些对go方法之外的c2变量的内容没有影响

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

假设
r2
是对
c2
的引用,假设
123
是该引用的值。 因此,
r2
“保持”
123
,这只不过是
c2的
位置


现在,当您调用
c1.go(c2)
时,将创建一个新的引用
rN
,它保存
123
,并传递给该方法。当您执行
c2=null
时,引用
rN
将变为
null
,而不是
c2
,要获得预期结果,请尝试使用

`System.out.print(cb.story);`
置零后的
go
方法中
cb

System.out.print(c3.story); // dout here
现在,在您的示例中,您将返回分配给
c3
null
。因此,您没有修改
c2
变量

我对这些疑问的最好解释是


所有答案和注释都值得一读。

在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)
)。

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

主要功能

  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引用上的story变量,您将看到它也会影响c2变量


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

他可能还想到了
System.out.print(c3.story)
,它将抛出一个NPE,因为
c3
将被分配
null
。现在刚刚编辑了什么…?@akf:可能,他会在那里得到一个NPE。@user1612062:只是改进了问题,仅此而已。原来是这样的:)@Bohemian:哇,没想到我会犯那样的拼写错误。。谢谢你纠正我,我感到惭愧!