异常
- 什么是异常
程序运行中发生错误导致没有办法继续执行的情况称为异常。异常处理得好坏予否意味着程序是否健壮和稳定。
异常由来:问题也是现实生活中一个具体的事物,也可以通过java类的形式进行描述,并封装成对象,其实就是java对不正常情况进行描述后的对象体系。 - error与exception的区别
Error类和Exception类都继承自Throwable类。
Exception:
1.可以是可被控制(checked) 或不可控制的(unchecked)。
2.表示一个由程序员导致的错误。
3.应该在应用程序级被处理。
Error:
1.总是不可控制的(unchecked)。
2.经常用来用于表示系统错误或低层资源的错误。
3.如何可能的话,应该在系统级被捕捉。 - 常见的异常
- 捕获异常
在Java中,如果某个方法抛出异常既可以在当前方法中进行捕捉,处理该异常,也可以将异常向上抛出,由方法调用者来处理。Java语言的异常处理器由try、catch、finally 3个语句块组成。其中,try语句块存放的是可能发生异常的Java语句;catch程序块在try语句块之后,用来激发被捕获的异常;finally语句块是异常处理结构的最后执行部分,不管try块中代码如何退出,都将执行finally块。
try块
若位于一个方法内部,并抛出一个异常(或在这个方法内部调用的另一个方法抛出了异常),那个方法 就会在抛出异常产生过程中退出。可在那个方法内部设置一个特殊的代码块,用它
捕获异常。这就叫作“try 块”,try 块属于一种普通的作用域,
用一个 try 关键字开头:
try {
// 可能产生异常的代码
}异常处理程序
抛出的异常必须在某个地方中止。这个“地方”便是异常处理程序。而且针对要捕获 的异常,都准备相应的处理程序。异常处理程序紧接在try 块后面,且用 catch(捕获)关键字标记。如下所示:
try {
//可能产生异常的代码
} catch(Type1 id1) {
// Handle exceptions of Type1
} catch(Type2 id2) {
// Handle exceptions of Type2
} catch(Type3 id3) {
// Handle exceptions of Type3
}
若抛出异常,异常处理机制就会搜寻自变量与异常类型相符的第一个处理程序。随后,它会进入那个catch 从句,并认为异常已得到处理(一旦catch 从句结束,对处理程序的搜索也会停止)。只有相符的catch 从句才会得到执行;
- 使用finally进行清理
对于一些代码,可能希望无论在try 块是否抛出,我们都想执行。对一些特定的操作,经常都会遇到这种情况,但在恢复内存时一般都不需要(因为垃圾收集器会自动照料一切)。为达到这个目的,可在异常处理程序的末尾使用一个finally 从句。所以完整的异常处理程序是这个样子:
try {
// 要保卫的区域:
// 可能“掷”出 A,B,或 C 的危险情况
} catch (A a1) {
// 控制器 A
} catch (B b1) {
// 控制器 B
} catch (C c1) {
// 控制器 C
} finally {
// 每次都会发生的情况
}
创建自定义异常
不一定非要Java中已有的异常。Java提供的异常体系是不可能预见所有的希望加以报告的错误,所以可以自定义异常类。
自己定义异常类,必须从已有的异常类继承,最好是选择意思相近的异常类继承。必须继承的原因:异常体系有一个特点:因为异常类和异常对象都被抛出,他们都具备可抛性。这个可抛性是Throwable这个体系中独有特点。这有这个体系中的类和对象才可以被throws和throw操作。
建立新的异常类型最简单的方法就是让编译器为你产生默认构造器:
例子1:下面编了一个加入数组下标小于0的自定义异常代码:
class MyException extends Exception{
public MyException (){
super("你的栈空了!!");
}
}
public class MyStack2 {
public static void main(String[] args) {
int max=4;
Object[] data = new Object[max];
int pos=2;
try{
if(pos<0){
throw new MyException();
}
}
catch(ArrayIndexOutOfBoundsException e){
e.printStackTrace();
}
catch(Exception e){
e.printStackTrace();
}
System.out.println(data[pos]);
}
}
例子2:
class SimpleException extends Exception{
}
public class MyException {
public void f() throws SimpleException{
System.out.println("Throw SimpleException from f()");
throw new SimpleException();
}
public static void main(String[] args) {
MyException sed = new MyException();
try{
sed.f();
}catch (SimpleException e){
System.out.println(" Caught it");
}
}
}
- 对多异常的处理
1.声明异常时,建议声明更为具体的异常;比如 : int div (int a , int b)throws ArithmeticException
2.声明几个异常,就要有对应的几个catch块,如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。
建议在进行catch处理时,catch中要有一定要定义具体的处理方式。不要用输出语句(如:e.toString、e.printStackTrace)。
例子如下:
class Demo{
int div(int a,int b)throws ArithmeticException,ArrayIndexOutOfBoundsException{
int [] array = new int[a];
System.out.println(array[5]);
return a/b;
}
}
public class MultiException {
public static void main(String[] args) {
Demo demo = new Demo();
try{
int x =demo.div(5, 0);
System.out.println("x:"+x);
}
catch(ArithmeticException e){
System.out.println("你的除数为0了");
}
catch(ArrayIndexOutOfBoundsException e){
System.out.println("你的数组角标越界了");
}
catch(Exception e){
System.out.println(e.toString());
}
}
}
- throws与throw的区别
位置不同: throws使用在函数上,throw使用在函数内;
throws后面跟的异常类,可以跟多个,用逗号隔开;throw后跟的是异常对象。