原始问题:
关于异常中,何时在该类中处理,何时抛给调用类处理,比较纠结。比如IO中new FileInputStream(),new InputStreamReader(fStream, "UTF-8");in.readLine()等他们异常哪些本类中处理,还是都抛给调用者。
讨论:
李:其实对于方法中的异常处理有两种方法:1、在该函数中用try...catch语句进行捕获和处理。2、直接抛出异常(这种做法有一点模糊,因为并不能确定该方法是否有异常),那么调用该方法的调用者就要处理这个方法的异常。也就是抛出异常的情况是抛给调用者去解决了。因为try..catch语句如果用的多的话,代码比较繁琐不易观看,所以才会有抛出一种异常这种做法吧 。
胡:这样写行吗?
FileInputStream fStream = null; InputStreamReader reader = null; BufferedReader in = null; try { fStream = new FileInputStream(path); reader = new InputStreamReader(fStream, "UTF-8");//将InputSteam转换成Reader in = new BufferedReader(reader); //只提供缓冲区的包装方法 //dosomething } catch (FileNotFoundException e) { throw e; } catch (SecurityException e) { throw e; } catch (UnsupportedEncodingException e) { throw e; } catch (IOException e) { throw e; }finally { try{ if (fStream != null) fStream.close();}catch (IOException e){log.warn("FileInputStream close failed");} try{ if (reader != null) reader.close();}catch (IOException e){log.warn("InputStreamReader close failed");} try{ if (in != null) in.close();}catch (IOException e){log.warn("BufferedReader close failed");} }
李:最好别嵌套写
胡:还是根本就不拥try
李: 要用try
胡:直接抛给调用者。
李:这个finally里边还有try..catch,就别这样嵌套写了
胡: 为什么呢? 还是不管什么异常都抛给调用者。 我嵌套,是因为close也抛出异常。 不这样做的话,可能某个流没有被关闭。 所以我特别的纠结,究竟该怎么写,有没有一套规范。
李: 像这种非运行时的异常直接抛出应该没问题
胡: 我这样写,我又有点嫌它写的太长了。
李: 这样确实很繁琐
胡:既然要抛出,索性,全部都丢给调用者。 那try也不用了。
李: 如果两种异常全部抛出,根据大小关系,调用者来两个catch。能行吗?
胡:你说的意思我有点模糊
李: 我还没试过直接抛出两种异常的代码,所以我也不清楚,调用者根据捕获的异常来处理,是否能处理呢?
胡: 你这个应该是能不能处理的。毕竟两种异常调用者很难去识别是哪一种异常。
李:恩,这个有点异议, 调用者应该知道抛出的是哪种异常啊
胡: 我的意思比如你要抛出io和math异常,那么就用throws Exception来抛出。 调用者接受的是Exception。 这样能识别出是哪种吗?
李: 恩,那没抛出math异常,在底层的方法里边应该用try...cathe来捕获math异常啊
胡: 是的。
这个问题也不知道怎么回事儿了,待大神解决。
还有两个问题:
1、java中垃圾回收器会自动检测不再被引用的对象,之后释放空间。释放空间之后java jvm会不会像C++给指针赋值NULL?而且java jvm快到耗尽的时候才调用垃圾回收机制,如果这时因为某些情况我必须要释放内存,自己定义finalize方法去实现,我怎么保证对象的空间一定被释放掉了?也就是finalize方法不是析构函数,是怎么被调用的?
2、Chanel可以用于线程间的通信,还有哪些应用场合,有什么好处?
(邓维佳)回答:
1.由外界不稳定性导致的异常,应该抛出,比如IO,
2.考虑出现异常的责任,如果在系统外,抛出
3.对于异常的处理,如果觉得可能处理不当,应该printstack,同时打印context信息,便于根据日志追查原因
4.嵌套的trycatch,两层就够了,第一层是主要逻辑,第二层,我觉得更多是语法要求。IO的异常被操作系统屏蔽的很好,除非权限问题,文件不存在,网络不通这类,assign给运维处理一下就能解决。所以不太可能外层try关闭和嵌套层try做同一个事情,一个成功一个不成功
5.处理异常的原因不仅仅是代码声明可能有异常发生,更主要的是需要考虑,我处理了异常是否合理,如果本身主调方传参有误导致异常,在方法开头就需要check,然后抛异常,对于不合法的请求,我们是没有办法做容错处理的
6.当然,有些情况的异常,在业务逻辑上是合法的,但是在java语法上不合法,这个时候我们就可以考虑内部处理。比如传一个数字进来,可以使Integer 可能是 String,可能是十进制,可能是十六进制,根据不同格式做相应转换。或者传入一个null,发生异常try掉,然后默认赋值为0.。。。