fanxin

 

为什么会发生空指针异常(NullPointException)




主  题:
为什么会发生空指针异常(NullPointException),它有什么坏处,怎么去避免它?我出100分,大家讨论讨论!




如题!

回复人: whyxx(永远成不了高手) ( ) 信誉:110 2003-12-12 16:55:05Z 得分:5


?
一个东西是null,就是说只有其名,没有实值内容,也没分配内存,当你要去取他的长度,对他进行操作当然就会NullPointException,
Top


回复人: qmei(上班java下班C#) ( ) 信誉:100 2003-12-12 16:55:37Z 得分:5


?
比如变量为空,而你没有去判断,就直接使用,就会出现
写程序时严谨些,尽量避免了
Top


回复人: xiaozuidazhi(以前不会用,导致信誉分低_我是好人!) ( ) 信誉:87 2003-12-12 17:00:54Z 得分:0


?
是不是说只有声明,没有创建?然后还用它做事情,然后就会出现这种情况?

但是,如果在jb中,没有进行初始化的变量一下子就看出来了啊,怎么还会有这种情况??
Top


回复人: Mailbomb(网络咖啡) ( ) 信誉:115 2003-12-12 17:21:45Z 得分:5


?
空指针异常发生在对象为空,但是引用这个对象的方法。例如:

String s = null; //对象s为空(null)
int length = s.length();//发生空指针异常
Top


回复人: ladofwind(随风) ( ) 信誉:100 2003-12-12 17:22:05Z 得分:0


?
jb自己带的这个功能啊,
所以会方便一些,
避免编译了才发现问题
Top


回复人: xiaohaiz(城里的老土,两眼依然通红!) ( ) 信誉:105 2003-12-12 17:35:25Z 得分:50


?
NullPointerException这个东西换一个角度来看,没准是好处也不一定。
可以说,NullPointerException本身也是JAVA安全机制的一部分。有UNIX写C和C++的经验的可能都知道,空指针会导致什么问题:经常会导致程序的崩溃。 :)
而JAVA在这点进行了改善,JAVA为了保证程序的强壮,总是会对对象的引用进行检查。所以不再出险C/C++中的空指针错误,而仅仅是一个运行级别的异常-“NullPointerException”。
从这点上说,算是JAVA的一个好处吧。
Top


回复人: binny(骑个破车看夕阳) ( ) 信誉:98 2003-12-12 17:51:31Z 得分:5


?
我记得以前看过一篇文章,里面提到尽量避免返回null,说方法的返回值不要定义成为一般的类型,而是用数组。这样如果想要返回null的时候,就返回一个没有元素的数组。就能避免许多不必要的NullPointerException

不知道各位对这种说法怎么看
Top


回复人: xiaohaiz(城里的老土,两眼依然通红!) ( ) 信誉:105 2003-12-12 18:00:55Z 得分:0


?
TO binny(骑个破车看夕阳):
俺记得Josha Bloch倒是在《Effective Java》中说过返回数组的函数,如果没有返回值,优先返回零长度数组而不是返回null。 :)
尽量避免返回null有什么好处,俺还没有想到。
不过使用NullObject返回代替返回null确是一种不错的选择。

BTW,你提到的做法实际上也是建立在双方的一个契约之上的。因为返回数组的方法同样可以返回null,因为数组在JAVA中已经发展为完备的对象了。如果是这样,INVOKER也是不可避免地检查NullPointerException。这样做俺个人意见是没有什么意义的。
Top


回复人: alphafish(alphafish) ( ) 信誉:100 2003-12-12 18:01:15Z 得分:5


?
在写代码御用一定的技巧可以有效的对null进行避免,例如,判断一个String的实例s是否等于“a”,不要写成s.equals("a"),这样写容易抛出NullPointerException,而写成"a".equals(s)就可以避免这个问题。
Top


回复人: lixiang823517(泥浆) ( ) 信誉:105 2003-12-12 18:01:35Z 得分:0


?
来晚了!
Top


回复人: chashui(茶水) ( ) 信誉:100 2003-12-12 18:56:15Z 得分:0


?
学习
Top


回复人: sunlen(伏枥) ( ) 信誉:100 2003-12-12 19:03:49Z 得分:0


?
谁说是jb的功能,在哪里编译都有
Top


回复人: mor(安稼) ( ) 信誉:100 2003-12-12 19:29:23Z 得分:5


?
to xiaohaiz(老土进城,两眼通红)
呵呵,我也想到了Bloch的那段话,在返回数组或者java.util类时,返回一个空数组或一个空的Vector之类,可以大大减少NullPointerException的出现概率,也省了很多if(XX==null)之类的判断。
Top


回复人: Eraserpro(穷...哪位好人拿钱砸我吧!!!) ( ) 信誉:110 2003-12-12 20:00:43Z 得分:5


?
其实我觉得主要看需求
打个比方,你做网站,你是希望看到没数据的栏空着还是希望看到一个null?
但做别的事情可能又是两样了

也不一定非得从程序中判断,数据库表中把相应字段设为not null很多时候也是一种好办法,从源头上避免了NullPointer,程序中根本连判断都可以免掉
Top


回复人: fantasyCoder(牛仔+T恤) ( ) 信誉:94 2003-12-12 20:17:47Z 得分:0


?
一个RunTimeException
Top


回复人: naolin2008(自由鸟) ( ) 信誉:95 2003-12-12 20:51:27Z 得分:0


?
学习中了!
!!!
Top


回复人: HurricanDavidLiu(俺啥也不懂) ( ) 信誉:92 2003-12-12 22:08:59Z 得分:0


?
mark
Top


回复人: zenius(飞云) ( ) 信誉:100 2003-12-12 22:52:37Z 得分:0


?
NullPointerException本身也是JAVA安全机制的一部分,通常的做法是在可能出现异常的地方try 一下,再catch 。
Top


回复人: qlampskyface(天空的样子) ( ) 信誉:100 2003-12-13 12:38:12Z 得分:0


?
看来这个问题还是挺值得讨论!
Top


回复人: qiume(杜克) ( ) 信誉:100 2003-12-13 12:58:28Z 得分:0


?
String str = null;
if (str == null) {
System.out.println("字符为空!");
}
Top


回复人: qlampskyface(天空的样子) ( ) 信誉:100 2003-12-13 13:49:45Z 得分:0


?
to:qiume(杜克)

这是干什么?当时声明的时候声明成
String str="";
不就得了吗?
Top


回复人: dreamnear(哟哟) ( ) 信誉:100 2003-12-13 14:19:12Z 得分:0


?
当对象为空的时候对该对象内容进行操作的时候就会出现NullPointException了。我觉得还是对变量先进行判空还后再进行操作比较好。
Top


回复人: qlampskyface(天空的样子) ( ) 信誉:100 2003-12-13 14:58:54Z 得分:10


?
我觉得还是养成赋空对象为初值的习惯比较好!
Top


回复人: hehecafe(我喜欢从高处跳下来的感觉) ( ) 信誉:98 2003-12-13 16:04:00Z 得分:0


?
同意 qlampskyface(天空的样子)
Top


回复人: xiaohaiz(城里的老土,两眼依然通红!) ( ) 信誉:105 2003-12-13 16:16:28Z 得分:0


?
TO qlampskyface(天空的样子):
初值不是你想决定是什么就是什么的。在很多情况下,你甚至无法断定对象的初值是什么才合适。所以这样的习惯并不见得就是很好的习惯。比如说你认为:
String str = ""; 这样比较合理,但是为什么不是
String str = "A"; 呢?在某些场合并不见得""就是合理的初值。

关键还是在建立publish方法的契约之上。如果你使用第三方的方法,你需要阅读其JAVADOC,知道其是否会返回null对象?是否会抛出checkedException,是否会抛出运行级别异常。
如果是你自己publish方法,那么你需要在你的JAVADOC中说明你的方法的契约:满足什么条件才能调用此方法,调用之后会产生什么返回?是否会返回/何时返回null?是否抛出异常。在实现publish方法的时候,对于入口参数的检查也是非常关键的,因为调用者的行为是你无法期望的。

Top


回复人: liujiwe79(独孤求胜) ( ) 信誉:100 2003-12-13 16:19:09Z 得分:0


?
大家说的都不错,想这种情况最好去判断,为空时抛异常
Top


回复人: qlampskyface(天空的样子) ( ) 信誉:100 2003-12-13 16:28:39Z 得分:0


?
看来我懂得不深!谢谢xiaohaiz
Top


回复人: qlampskyface(天空的样子) ( ) 信誉:100 2003-12-13 16:50:24Z 得分:0


?
to  xiaohaiz

老土兄

不过如果用jb开发的话,像这些异常它会报告的,怎么还会出现很多人说的这个毛病呢?
Top


回复人: xiaohaiz(城里的老土,两眼依然通红!) ( ) 信誉:105 2003-12-13 17:02:50Z 得分:0


?
TO qlampskyface(天空的样子) :
呵呵,首先这和你用什么IDE来做开发是没有任何问题的。:)
NullPointerException由RuntimeException派生出来,是一个运行级别的异常。意思是说可能会在运行的时候才会被抛出,而且需要看这样的运行级别异常是否会导致你的业务逻辑中断。

就不多说了。其实异常的处理是一个很有意思的话题,不仅仅只是NullPointerException。比如在DBC中有这么一个例子:
你需要打开一个文件读,可能是C:\Data.txt,文件却没有找到,叫不叫异常?
你如果需要打开另外一个文件,比如是C:\boot.ini,文件也没有找到,叫不叫异常?
第一种情况不叫“异常”,因为C:\Data.txt没有找到应该是你能预计到的情况,那个文件可能存在,也可能不存在,这是需要你自己处理的。而第二种情况确叫做异常,因为正常情况下,C:\boot.ini应该被期望存在的,如果运行时丢失了这个文件,就是运行级别异常。
在JDK中也有相应的例子,比如FileInputStream, BufferReader, StringTokenizer处理到达尾部的情况就是不一样的。
Top


回复人: hlding(淋东) ( ) 信誉:82 2003-12-13 17:14:46Z 得分:0


?
这种情况通常发生在如下情况:定义了(或者声明)某个对象,但并没有给他赋值,而在后续的程序中却又要取值,这个时候就会出现NullPointerException异常了
Top


回复人: hlding(淋东) ( ) 信誉:82 2003-12-13 17:15:20Z 得分:0


?
比如:String s;System.out.println(s);
Top


回复人: fantasyCoder(牛仔+T恤) ( ) 信誉:94 2003-12-13 17:26:11Z 得分:5


?
NullPointerException
在编译期是不用捕获的
在运行期由jvc捕获

Top


回复人: qlampskyface(天空的样子) ( ) 信誉:100 2003-12-13 17:58:16Z 得分:0


?
to hlding(淋东) 

String s;System.out.println(s);这种情况不是运行级别异常,而是编译级别异常

to xiaohaiz(老土进城,两眼通红)

那我觉得每个程序员都应该努力去避免这种情况,比如,能声明空对象的尽量声明空对象,不要图省事用null代替。
要是真的碰到了不得不声明为null的method时,应该在方法内部给出提示,尽量让用这个方法的人在编译级别就解决它。但是我不知道这样能不能达到。

比如我写的一个方法:

public ResultSet returnRandom(String tname,int rnum)
{//在某表里随机取出rnum个记录
ResultSet rd=null;
String random="select * from (select "+tname+".*,dbms_random.random num from sysusers orderby num) where rownum<"+rnum;//随机取得该地图的一个位置
try{
rd = ora.dealDB(random);
}
catch(ClassNotFoundException e){
System.out.println("Class not found exception"+e.getMessage());
}
catch(SQLException e){
System.out.println("SQL exception: "+e.getMessage());
}
return rd;
}
这里的这个结果集我觉得好像不得不声明为null了,但是我想在方法里抛出一个空指针异常,让用这个方法的人直接就捕捉这个异常,这样,不就很安全了吗?

但是我不知道怎么样才能达到以上要求,请你指正!
Top


回复人: showerXP(小阿!) ( ) 信誉:97 2003-12-13 18:19:19Z 得分:0


?
不是说java没有指针了吗?thinking in java也是用reference来代替。其实应该说是object是空才对,基本类型你不给初值也可以,但是object就不行了。典型的就是楼上的例子,有NUll异常出现还好,起码知道你的代码是什么错误。csdn文档有“你的代码健壮吗”文章就有关于null的。
Top


回复人: xiaohaiz(城里的老土,两眼依然通红!) ( ) 信誉:105 2003-12-13 18:24:47Z 得分:0


?
TO qlampskyface(天空的样子):
呵呵,你发现没有:“如果使用java.sql.ResultSet”来返回你所需要的结果,会令你的逻辑变得很别扭?如果这样问题就可以变化成这样了,你选择使用ResultSet来作为返回结果是不恰当的。

如果需要返回不定长的结果集使用什么?使用List或者直接使用数组。

如果一定要这么做,你应该保证不会返回null的ResultSet,如果出现任何异常,那么需要抛到方法的外部去,而不在内部消化。看你的代码ClassNotFoundException和SQLException都是真正的异常,只要出现就代表了意外发生,这样的情况当然应该处理,而不是简单地返回null就消化了。比如可以变成这样:
<<
/**
* Get random Results of given Table by given row number.
*
* @param String tname Table name.
* @param int rnum Row number.
* @return Random result set, NEVER return null.
* @throws ClassNotFoundException If ...
* @throws SQLException If ...
*/
public ResultSet returnRandom(String tname,int rnum) throws ClassNotFoundException, SQLException {
// Your code here...
}
>>
Top


回复人: qlampskyface(天空的样子) ( ) 信誉:100 2003-12-13 18:38:04Z 得分:0


?
to xiaohaiz(老土进城,两眼通红)
---------------------------------------------------------------------------------
1.我上面的只是个例子,想问的是如果方法中有可能有null返回,那么方法外面只能先判断是否为null吗?有没有更好的方法,在编译级别就能够解决的,这样不是更好吗?
2.但是这两个异常并不包括空指针异常啊
3.就算我抛这两个异常到外面去的话,我也是这样的处理方式啊,如果都这样处理的话,那么在里面处理和在外面处理有不同吗?
4.为什么说ResultSet作为处理结果不恰当呢?
---------------------------------------------------------------------------------
老土兄,你说吧,我听你的。
Top


回复人: qlampskyface(天空的样子) ( ) 信誉:100 2003-12-13 18:48:45Z 得分:0


?
还有啊,我返回结果集是因为不能确定要操作的是哪个列,这样在外面就可以操作结果集中的任何一个列了啊。
Top


回复人: qlampskyface(天空的样子) ( ) 信誉:100 2003-12-13 19:28:28Z 得分:0


?
顶一下,等!
Top


回复人: maybekolo(恐龙) ( ) 信誉:99 2003-12-13 19:39:36Z 得分:0


?
嗯。。期待
Top


回复人: xiaohaiz(城里的老土,两眼依然通红!) ( ) 信誉:105 2003-12-13 20:55:16Z 得分:0


?
TO qlampskyface(天空的样子) :
<<
1.我上面的只是个例子,想问的是如果方法中有可能有null返回,那么方法外面只能先判断是否为null吗?有没有更好的方法,在编译级别就能够解决的,这样不是更好吗?
>>
确实有更好的方法来解决,使用NullObject来解决这种问题是很好的选择。
比如:
public interface SomeInterface {
public void doSomething();
}
你可能实现了多个
public class ConcreateA implements SomeInterface {...}
public class ConcreateB implements SomeInterface {...}
...

假设你需要根据某种策略来选择具体的实现类,比如在工厂方法中有:
public SomeInterface getConcreateInstance(String arg) {
// 根据参数选择不同的具体实现类实例返回。
}
这个时候问题就出现了,如果参数错误了,如何返回具体类实例呢?假设返回null。
<<
if (arg is invaild) {return null;}
>>
那么客户端就必须作null检查了。
<< In client:
SomeInterface si = getConcreateInstance(arg);
if(si == null ) {// handle null here
... ...
}
>>
如果引入Null Object,就可以更优雅地解决这个问题。
可以做一个NULL实现,比如:
<<
public class NullImpl implements SomeInterface {
public void domSomething(...);
}
>>
在工厂方法中,如果参数错误,则不必返回null,而是返回此NullImpl的实例:
<<
if ( arg is invalid ) {return new NullImpl();}
---------------------------------------------
private static final SomeInterface NULL_IMPL = new NullImpl();
if( arg is invalid ) {return NULL_IMPL;} // better.
>>
这样客户端就可以不必做null检查了。 :)
<< In client:
SomeInterface si = getConcreateInstance(arg);
si.doSomething();
>>
这样的NULL_OBJECT模式处理这类的问题非常方便。

Top


回复人: xiaohaiz(城里的老土,两眼依然通红!) ( ) 信誉:105 2003-12-13 21:04:31Z 得分:0


?
<<2.但是这两个异常并不包括空指针异常啊>>
A: 确实不包括NullPointerException,你的例子中不应该抛出此异常(除了参数检查处可以抛出此异常,在检查参数的时候,如果参数为null导致无法继续可以抛出NullPointerException或者IllegalArgumentException,这个时候基本可以等价看待这两个异常)

<<3.就算我抛这两个异常到外面去的话,我也是这样的处理方式啊,如果都这样处理的话,那么在里面处理和在外面处理有不同吗?>>
自己好好想想为什么在里面处理和外面处理不同?俺就说一个小原因:
假设你是此类库的提供者,而俺是使用之的客户。如果我使用此方法,返回了null,那么是代表确实没有结果返回还是因为发生了数据库错误或者是别的什么?俺看俺是一定要糊涂的。所以说publish的方法的异常是很讲究的。

<<4.为什么说ResultSet作为处理结果不恰当呢?>>
把不相关的东西耦合在了一起。把JDBC query的结果集逻辑和自己需要的数据聚集的逻辑耦合在了一起。这样连抽象都无法做。现在俺们是从数据库中随机取结果,所以你使用了ResultSet,假设需求变化了,需要从文本文件源中取结果了,你的ResultSet接口成了什么?
所以说更好的做法是抽象出数据获取的接口,而针对接口不同实现即可。
:) “单一职责”这点很关键,不需要耦合在一起的东西就不要耦合在一起。

Top


回复人: qlampskyface(天空的样子) ( ) 信誉:100 2003-12-13 21:13:09Z 得分:0


?
我觉得你说得很多东西我都觉得很有内涵,我只理解了个皮毛,还都得去认真得学习,我会保存好这篇文章,时不时拿出来看看的,真心谢谢你,老土兄!
Top


回复人: longskyhw(长空恨水) ( ) 信誉:99 2003-12-13 21:38:43Z 得分:0


?
NullPointerException空指针异常,既然为异常就不是编译时期能够扑获到的,jb等ide只会检查出语法错误,不会检查出运行期的逻辑错误。
对于xiaohaiz(老土进城,两眼通红)说的用Null Object代替null,我认为不是太好的方法,这等于是对client端没有约束,个人认为不够严谨,不强制client端检查null,可能对程序的健壮性和正确性有影响。
NullPointerException大多是非预期的结果,既然是非预期的值,当然应该在用此值之前进行判断,对数据做前期检查是程序员必做的,否则如何保证程序健壮。
Top



结贴 ,得分记录: whyxx (5)、 qmei (5)、 Mailbomb (5)、 xiaohaiz (50)、 binny (5)、 alphafish (5)、 mor (5)、 Eraserpro (5)、 qlampskyface (10)、 fantasyCoder (5)、

posted on 2006-01-17 21:50 fanxin 阅读(11037) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 

导航

统计

留言簿

文章档案

Java

matrix

weiqin

中国JSP技术网站

搜索

最新评论