您的位置:首页 > 编程语言 > Java开发

看完这篇文章包你Java空指针问题迎刃而解

2018-03-16 09:51 465 查看
昨晚跟朋友们讨论了一个有关空指针的问题,觉的有意义将其写下来。

问题如下面这段代码:

朋友觉的这段代码不可能编译通过,觉的会报空指针异常,但事实上它是能编译通过且正常运行的,由此引发了我们的讨论,在此做一下总结。

首先声明,我们都还是学生,水平和能力有限,基础不牢、代码经验都不丰富,还望各位大神勿喷,有错误或者各位网友有想法的欢迎评论。

下面来一行行分析这段代码(时刻要从计算机的角度去考虑程序代码):

首先 List<User> list = new ArrayList<>();  这行代码是告诉计算机你去堆内存上给我开辟一个空间,把new ArrayList<>()产生的实例放进去,并给它一个地址方便程序能找到它。

于是计算机勤劳的帮您去完成了这件事,并把创建完成后的实例的地址返回给了List<User> list 中的list变量。

程序执行完这行代码知道了:①内存中有一个List类型的实例 ②我的list变量也已经拿到了该实例在内存中的地址,随时做好哪里需要就在哪里引用这个实例就行了。

接着 User user = new User(); 这行代码跟上面也是同理,我就直接给结论了:①内存中有一个User类型的实例 ②我的user变量已经拿到了该实例的在内存中的地址(这里假设该地址就是123)。

再接着 list.add(user); 我们通常的理解就是list对象调用add方法,然后将user对象放进去,这样理解没错,但是我这里要把地址考虑进去就是这样理解的:如前面所说的list其实存放的是地址,通过这个地址程序才能去内存中找到实例,同样user存放的也是地址,通过这个地址也能去内存找到实例。所以 list.add(user); 这行代码从程序的角度理解就是:程序通过list里面的地址去内存中找到List类型的实例来调用add方法,然后add方法里通过user里面存放的地址在内存找到User类型的实例。

再接着 user=null; 其实就是在程序中把程序里的user变量里面存放的地址置为空(然而内存中new User()实例的地址还在内存中一直没改变过)。

所以 list.get(0).getClass(); 这行代码是能正常执行的,编译运行都是没问题的。分析:通过list变量里面的地址在内存中找到List类的实例,该实例调用get(0)方法取出list集合里面存放的User类实例的地址(注意list.add(user)执行完了list集合里面第0位存放的就是内存中User类的实例的地址123,这里通过list.get(0)当然取到的也是这个地址,当然就能在内存中找到User类的实例,因为内中它的地址一直没改变过)

概括起来理解就如下图

为了证明上面的说法请看下面的例子,这样就会报空指针:

这是因为:

31行在list里面放了一个空地址null,然后35行试图通过这个空地址去内存找到某个对象来调用getClass()方法,这样程序在内存中肯定没法找到这个地址,不能通过这个地址找到对象因此就是空指针了。

不加29行的代码,那么list里面第0位放的就是地址123(可以找到内存中地址为123的那个实例),如果加了29行那么list里面第0位放的就是地址null(一个空地址去匹配内存中的对象的地址永远也匹配不上,所以就空指针)。

内存中每个实例的地址如果在程序里面没有被使用,那么垃圾回收机制就起作用了。

总结到此结束,有问题我会抽空修正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  空指针