Java异常处理

来源:互联网 发布:mac 删除软件 编辑:程序博客网 时间:2024/05/01 23:47

异常处理的任务就是要将控制权从产生错误的地方传给能够处理这种情况的错误处理器。

可能出现的错误和问题:

1.用户输入错误     2.设备错误     3.物理限制    4.代码错误

异常的分类:


从上图可知:所有的异常都是由Throwable继承而来,但在下一层立即分解为两个分支ErrorException

Error类层次结构描述了Java运行时系统内部错误和资源耗尽错误。应用程序不应该抛出这种类型的对象。

在进行Java程序设计的时候,需要关注Exception层次结构。这个层次结构又分解为两个分支:一个分支派生于RuntimeException的异常;另一个分支包含其他异常。划分两个分支的规则是:由程序错误导致的异常属性RuntimeException;曾经能够正确运行,而由于某些情况(例如,I/O错误)导致的异常不属于RuntimeException。

RuntimeException:错误的类型转换、数组访问越界、访问空指针。

如果出现RuntimeException异常,就一定是你的问题” 是一条相当有道理的规则。应该通过检测数组下标是否越界来避免ArrayIndexOutOfBoundsException异常;应该通过在使用变量之前检测是否为空来杜绝NullPointerException异常的发生。不要总依赖于运行程序来发现错误,在有信心没有错误了,再去运行。

非RuntimeException:试图在文件尾部后面读取数据、试图打开一个错误格式的URL、试图根据给定的字符串查找Class对象,而这个字符串表示的类并不存在。

下面看一个简单的例子:

public class TestException {public static void main(String[] args) {try {test();} catch (IOException e) {// TODO something with Exception}try {test2(1, 2);} catch (Exception e) {// TODO something with Exception}try {test2(2, 1);} catch (Exception e) {// TODO something with Exception}}public static void test() throws IOException {//TODO something may generate IOException}public static void test2(int a, int b) throws Exception {if (a < b) {throw new IOException();} else {throw new ArrayIndexOutOfBoundsException();}}}

对于方法test(),它自己不知怎么处理可能会产生的异常,然后就抛出去,让有能力处理的地方去处理,此处是在主main函数中try..catch...捕获异常进行处理。

对于方法test2(int,int),也相似,在内部抛出异常,最终还是由整个方法去抛。

其中的try...catch...或throws是必须的,否则编译报错,如:

这时,要么...main(String[] args) throws Exception,要么try...catch...包起来。

一旦将异常抛出,调用这个方法的方法就要对异常进行处理,或再抛出让更上层去处理。

下面来看下相关类API:



使用异常机制的建议:

1)异常处理不能代替简单的测试

2)不要过分地细化异常

3)利用异常层次结构

4)不要压制异常

5)在检测错误时,“苛刻”要比放任更好

6)不要羞于传递异常

下面来看一个异常堆栈:

07-22 18:41:07.121: E/test(7770): error stacktrace:7
07-22 18:41:07.184: E/AndroidRuntime(7770): FATAL EXCEPTION: pool-4-thread-1
07-22 18:41:07.184: E/AndroidRuntime(7770): java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
07-22 18:41:07.184: E/AndroidRuntime(7770): at com.vidmt.acmn.utils.optional.java.DynProxyUtil$MyInvocationHandler.invoke(DynProxyUtil.java:38)
07-22 18:41:07.184: E/AndroidRuntime(7770): at $Proxy0.setUserInfo(Native Method)
07-22 18:41:07.184: E/AndroidRuntime(7770): at com.vidmt.letsgo.managers.inner.InnerAccManagerImpl.setUserInfo(InnerAccManagerImpl.java:145)
07-22 18:41:07.184: E/AndroidRuntime(7770): at com.vidmt.letsgo.activities.AccountSetActivity$8$1.run(AccountSetActivity.java:312)
07-22 18:41:07.184: E/AndroidRuntime(7770): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
07-22 18:41:07.184: E/AndroidRuntime(7770): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
07-22 18:41:07.184: E/AndroidRuntime(7770): at java.lang.Thread.run(Thread.java:838)
07-22 18:41:07.184: E/AndroidRuntime(7770): Caused by: java.lang.reflect.InvocationTargetException
07-22 18:41:07.184: E/AndroidRuntime(7770): at java.lang.reflect.Method.invokeNative(Native Method)
07-22 18:41:07.184: E/AndroidRuntime(7770): at java.lang.reflect.Method.invoke(Method.java:525)
07-22 18:41:07.184: E/AndroidRuntime(7770): at com.vidmt.letsgo.http.HttpManager$1.invoke(HttpManager.java:36)
07-22 18:41:07.184: E/AndroidRuntime(7770): at com.vidmt.acmn.utils.optional.java.DynProxyUtil$MyInvocationHandler.invoke(DynProxyUtil.java:31)
07-22 18:41:07.184: E/AndroidRuntime(7770): ... 6 more
07-22 18:41:07.184: E/AndroidRuntime(7770): Caused by: com.vidmt.letsgo.exeptions.VidException: code:10->code:10
07-22 18:41:07.184: E/AndroidRuntime(7770): at com.vidmt.letsgo.http.inner.InnerHttpManagerImpl.getCorrectJsonResult(InnerHttpManagerImpl.java:376)
07-22 18:41:07.184: E/AndroidRuntime(7770): at com.vidmt.letsgo.http.inner.InnerHttpManagerImpl.setUserInfo(InnerHttpManagerImpl.java:258)
07-22 18:41:07.184: E/AndroidRuntime(7770): ... 10 more
07-22 18:41:07.202: E/MobclickAgent(7770): onEndSession called before onStartSession
07-22 18:41:07.211: E/MobclickAgent(7770): onEndSession called before onStartSession

异常堆栈:


对于一个Throwable,它是由哪个异常包装类转换来的呢?即要得到“诱饵”,下面看一个方法:

参考:instanceof, isinstance,isAssignableFrom的区别

public static <T> T getCause(Throwable srcEx, Class<T> exType) {while (srcEx != null) {if (exType.isAssignableFrom(srcEx.getClass())) {return (T) srcEx;}srcEx = srcEx.getCause();}return null;}

XException xEx = getCause(e, XException.class);

0 0