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了,但是我想在方法里抛出一个空指针异常,让用这个方法的人直接就捕捉这个异常,这样,不就很安全了吗?但是我不知道怎么样才能达到以上要求,请你指正!
不是说java没有指针了吗?thinking in java也是用reference来代替。其实应该说是object是空才对,基本类型你不给初值也可以,但是object就不行了。典型的就是楼上的例子,有NUll异常出现还好,起码知道你的代码是什么错误。csdn文档有“你的代码健壮吗”文章就有关于null的。
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... } >>
to xiaohaiz(老土进城,两眼通红) --------------------------------------------------------------------------------- 1.我上面的只是个例子,想问的是如果方法中有可能有null返回,那么方法外面只能先判断是否为null吗?有没有更好的方法,在编译级别就能够解决的,这样不是更好吗? 2.但是这两个异常并不包括空指针异常啊 3.就算我抛这两个异常到外面去的话,我也是这样的处理方式啊,如果都这样处理的话,那么在里面处理和在外面处理有不同吗? 4.为什么说ResultSet作为处理结果不恰当呢? --------------------------------------------------------------------------------- 老土兄,你说吧,我听你的。
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模式处理这类的问题非常方便。
int length = s.length();//发生空指针异常
可以说,NullPointerException本身也是JAVA安全机制的一部分。有UNIX写C和C++的经验的可能都知道,空指针会导致什么问题:经常会导致程序的崩溃。 :)
而JAVA在这点进行了改善,JAVA为了保证程序的强壮,总是会对对象的引用进行检查。所以不再出险C/C++中的空指针错误,而仅仅是一个运行级别的异常-“NullPointerException”。
从这点上说,算是JAVA的一个好处吧。
俺记得Josha Bloch倒是在《Effective Java》中说过返回数组的函数,如果没有返回值,优先返回零长度数组而不是返回null。 :)
尽量避免返回null有什么好处,俺还没有想到。
不过使用NullObject返回代替返回null确是一种不错的选择。BTW,你提到的做法实际上也是建立在双方的一个契约之上的。因为返回数组的方法同样可以返回null,因为数组在JAVA中已经发展为完备的对象了。如果是这样,INVOKER也是不可避免地检查NullPointerException。这样做俺个人意见是没有什么意义的。
呵呵,我也想到了Bloch的那段话,在返回数组或者java.util类时,返回一个空数组或一个空的Vector之类,可以大大减少NullPointerException的出现概率,也省了很多if(XX==null)之类的判断。
打个比方,你做网站,你是希望看到没数据的栏空着还是希望看到一个null?
但做别的事情可能又是两样了也不一定非得从程序中判断,数据库表中把相应字段设为not null很多时候也是一种好办法,从源头上避免了NullPointer,程序中根本连判断都可以免掉
if (str == null) {
System.out.println("字符为空!");
}
String str="";
不就得了吗?
初值不是你想决定是什么就是什么的。在很多情况下,你甚至无法断定对象的初值是什么才合适。所以这样的习惯并不见得就是很好的习惯。比如说你认为:
String str = ""; 这样比较合理,但是为什么不是
String str = "A"; 呢?在某些场合并不见得""就是合理的初值。关键还是在建立publish方法的契约之上。如果你使用第三方的方法,你需要阅读其JAVADOC,知道其是否会返回null对象?是否会抛出checkedException,是否会抛出运行级别异常。
如果是你自己publish方法,那么你需要在你的JAVADOC中说明你的方法的契约:满足什么条件才能调用此方法,调用之后会产生什么返回?是否会返回/何时返回null?是否抛出异常。在实现publish方法的时候,对于入口参数的检查也是非常关键的,因为调用者的行为是你无法期望的。
呵呵,首先这和你用什么IDE来做开发是没有任何问题的。:)
NullPointerException由RuntimeException派生出来,是一个运行级别的异常。意思是说可能会在运行的时候才会被抛出,而且需要看这样的运行级别异常是否会导致你的业务逻辑中断。就不多说了。其实异常的处理是一个很有意思的话题,不仅仅只是NullPointerException。比如在DBC中有这么一个例子:
你需要打开一个文件读,可能是C:\Data.txt,文件却没有找到,叫不叫异常?
你如果需要打开另外一个文件,比如是C:\boot.ini,文件也没有找到,叫不叫异常?
第一种情况不叫“异常”,因为C:\Data.txt没有找到应该是你能预计到的情况,那个文件可能存在,也可能不存在,这是需要你自己处理的。而第二种情况确叫做异常,因为正常情况下,C:\boot.ini应该被期望存在的,如果运行时丢失了这个文件,就是运行级别异常。
在JDK中也有相应的例子,比如FileInputStream, BufferReader, StringTokenizer处理到达尾部的情况就是不一样的。
在编译期是不用捕获的
在运行期由jvc捕获
要是真的碰到了不得不声明为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了,但是我想在方法里抛出一个空指针异常,让用这个方法的人直接就捕捉这个异常,这样,不就很安全了吗?但是我不知道怎么样才能达到以上要求,请你指正!
呵呵,你发现没有:“如果使用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...
}
>>
---------------------------------------------------------------------------------
1.我上面的只是个例子,想问的是如果方法中有可能有null返回,那么方法外面只能先判断是否为null吗?有没有更好的方法,在编译级别就能够解决的,这样不是更好吗?
2.但是这两个异常并不包括空指针异常啊
3.就算我抛这两个异常到外面去的话,我也是这样的处理方式啊,如果都这样处理的话,那么在里面处理和在外面处理有不同吗?
4.为什么说ResultSet作为处理结果不恰当呢?
---------------------------------------------------------------------------------
老土兄,你说吧,我听你的。
<<
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模式处理这类的问题非常方便。
A: 确实不包括NullPointerException,你的例子中不应该抛出此异常(除了参数检查处可以抛出此异常,在检查参数的时候,如果参数为null导致无法继续可以抛出NullPointerException或者IllegalArgumentException,这个时候基本可以等价看待这两个异常)<<3.就算我抛这两个异常到外面去的话,我也是这样的处理方式啊,如果都这样处理的话,那么在里面处理和在外面处理有不同吗?>>
自己好好想想为什么在里面处理和外面处理不同?俺就说一个小原因:
假设你是此类库的提供者,而俺是使用之的客户。如果我使用此方法,返回了null,那么是代表确实没有结果返回还是因为发生了数据库错误或者是别的什么?俺看俺是一定要糊涂的。所以说publish的方法的异常是很讲究的。<<4.为什么说ResultSet作为处理结果不恰当呢?>>
把不相关的东西耦合在了一起。把JDBC query的结果集逻辑和自己需要的数据聚集的逻辑耦合在了一起。这样连抽象都无法做。现在俺们是从数据库中随机取结果,所以你使用了ResultSet,假设需求变化了,需要从文本文件源中取结果了,你的ResultSet接口成了什么?
所以说更好的做法是抽象出数据获取的接口,而针对接口不同实现即可。
:) “单一职责”这点很关键,不需要耦合在一起的东西就不要耦合在一起。
对于xiaohaiz(老土进城,两眼通红)说的用Null Object代替null,我认为不是太好的方法,这等于是对client端没有约束,个人认为不够严谨,不强制client端检查null,可能对程序的健壮性和正确性有影响。
NullPointerException大多是非预期的结果,既然是非预期的值,当然应该在用此值之前进行判断,对数据做前期检查是程序员必做的,否则如何保证程序健壮。