你真的了解Android异常处理吗
前言
在Android的开发调试过程中,遇到各种异常是再经常不过的事情了,除非你只是看看代码,或者你属于那种大牛级人物编写的代码不会产生异常。那么虽然我们经常和异常打交道,可是我们真的了解他吗,下面的篇幅我们来细说一下Android异常。
一. 什么是异常
异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。比如说,对对象没有进行初始化就是用,那么会抛去NullPointerException提示空指针错误;如果你用System.out.println(11/0),那么你是因为你用0做了除数,会抛出 java.lang.ArithmeticException 的异常。
常见的异常发生的原因有很多,通常包含以下几大类:
- 用户输入了非法数据
- 要打开的文件不存在
- 网络通信时连接中断,或者JVM内存溢出
这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。
要理解Android异常处理是如何工作的,你需要掌握以下三种类型的异常:
检查型异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
错误: 是指程序运行过程中较为严重的不可挽回的问题,大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。比如OutOfMemeryError,一旦出现错误程序就要挂。
二. Exception的继承关系
所有的异常类是从 java.lang.Exception 类继承的子类。Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。Android程序通常不捕获错误。错误一般发生在严重故障时,它们在Android程序处理的范畴之外。Error 用来指示运行时环境发生的错误。
例如,JVM 内存溢出。一般地,程序不会从错误中恢复。
异常类有两个主要的子类:IOException 类和 RuntimeException 类。可以使用如下的类图关系图表示
三. Android内置异常类
由于Android的基础语言是Java,所以Android的内置异常类和Java 内置异常类类似。
Java 语言定义了一些异常类在 java.lang 标准包中。标准运行时异常类的子类是最常见的异常类。由于 java.lang 包是默认加载到所有的 Java 程序的,所以大部分从运行时异常类继承而来的异常都可以直接使用。
3.1 Java常见非检查型异常
异常 | 描述 |
---|---|
ArithmeticException | 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。 |
ArrayIndexOutOfBoundsException | 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。 |
ArrayStoreException | 试图将错误类型的对象存储到一个对象数组时抛出的异常。 |
ClassCastException | 当试图将对象强制转换为不是实例的子类时,抛出该异常。 |
IllegalArgumentException | 抛出的异常表明向方法传递了一个不合法或不正确的参数 |
IllegalMonitorStateException | 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。 |
IllegalStateException | 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。 |
IllegalThreadStateException | 线程没有处于请求操作所要求的适当状态时抛出的异常。 |
IndexOutOfBoundsException | 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。 |
NegativeArraySizeException | 如果应用程序试图创建大小为负的数组,则抛出该异常。 |
NullPointerException | 当应用程序试图在需要对象的地方使用 null 时,抛出该异常 |
NumberFormatException | 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。 |
SecurityException | 由安全管理器抛出的异常,指示存在安全侵犯。 |
StringIndexOutOfBoundsException | 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。 |
UnsupportedOperationException | 当不支持请求的操作时,抛出该异常。 |
3.2 Java中常见的检查型异常
异常 | 描述 |
---|---|
ClassNotFoundException | 应用程序试图加载类时,找不到相应的类,抛出该异常。 |
CloneNotSupportedException | 当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。 |
IllegalAccessException | 拒绝访问一个类的时候,抛出该异常。 |
InstantiationException | 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。 |
InterruptedException | 一个线程被另一个线程中断,抛出该异常。 |
NoSuchFieldException | 请求的变量不存在 |
NoSuchMethodException | 请求的方法不存在 |
四. 检查型异常和非检查型异常的区别
前面说了这么多检查性异常和非检查性异常,可能会有读者纳闷究竟什么是检查型异常和非检查型异常,它们的联系和区别是什么呢。首先通过文字来描述一下:
检查型异常:Exception是检查型异常,在程序中必须使用try…catch进行处理,如果不不捕获该异常会导致程序编译不通过;
非检查型异常:RuntimeException是非检查型异常,例如NumberFormatException,可以不使用try…catch进行处理,但是如果产生异常,则异常将由JVM进行处理。下面我们通过具体的实例代码来说明问题:
package com.xxx.api.fun;
public class ExceptionFun {
/**
* 运行时异常,编译时不检查,可以不使用try...catch捕获
* @throws RuntimeException
*/
public static void RuntimeExceptionFun()throws RuntimeException{
throw new RuntimeException("运行时异常");
}
/**
* Exception异常,编译时会检查,必须使用try...catch捕获
* @throws Exception
*/
public static void ExceptionFun()throws Exception{
throw new Exception("Exception异常");
}
public static void main(String[] args) {
ExceptionFun();
RuntimeExceptionFun();
}
}
我们发现ExceptionFun()标红,IDE工具提示如下的异常错误,那么这里就是所说的检查型异常错误,这种错误一般IDE工具都会帮我们检查出来。
我们对ExceptionFun()加上try…catch来捕获异常,此时IDE工具就不会提示相关的检测型异常错误,可以正常编译通过了。
package com.xxx.api.fun;
public class ExceptionFun {
/**
* 运行时异常,编译时不检查,可以不使用try...catch捕获
* @throws RuntimeException
*/
public static void RuntimeExceptionFun()throws RuntimeException{
throw new RuntimeException("运行时异常");
}
/**
* Exception异常,编译时会检查,必须使用try...catch捕获
* @throws Exception
*/
public static void ExceptionFun()throws Exception{
throw new Exception("Exception异常");
}
public static void main(String[] args) {
try {
ExceptionFun();
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("Exception异常被捕获,打印相关异常信息:");
e.printStackTrace();
}
RuntimeExceptionFun();
}
}
最后运行一下,查看相关的输出结果,可以看出来检查型异常被捕获了,而运行时异常我们没有使用try…catch进行捕获而直接由系统抛出了相关的异常信息。
Exception异常被捕获,打印相关异常信息:
java.lang.Exception: Exception异常
at com.xxx.api.fun.ExceptionFun.ExceptionFun(ExceptionFun.java:17)
at com.xxx.api.fun.ExceptionFun.main(ExceptionFun.java:22)
Exception in thread "main" java.lang.RuntimeException: 运行时异常
at com.xxx.api.fun.ExceptionFun.RuntimeExceptionFun(ExceptionFun.java:9)
at com.xxx.api.fun.ExceptionFun.main(ExceptionFun.java:29)
总结
如上就是我对Android异常的一些总结,当然Android的异常还有很多的知识点可以讲解的,就不再本篇细述了。如果能对各位的实际工作或者面试能有一定的帮助,那我就感到非常的高兴了。