异常:顾名思义就是程序出现了不正常的情况。它是java中非常重要的功能,它可以帮助我们在遇到编译错误或者运行时错误能够做出判断并使程序继续执行。
异常的分类
- Throwable类是整个java异常体系的超类,所有的异常类都派生自这个类,包含Error和Exception这两个子类。
- Error表示程序在运行期间出现了十分严重、不可恢复的错误,在这种情况下应用程序只能中止运行,例如JAVA虚拟机出现错误。在程序中不用捕获Error类型的异常。一般情况下,在程序中也不应该抛出Error类型的异常。
- Exception是应用层面上最顶层的异常类,包含运行时异常 和 编译时异常。
关于异常
异常的一般性语法为:
try {
// 有可能抛出异常的代码
} catch (Exception e) {
// 异常处理
} finally {
// 无论是否捕获到异常都会执行的程序
try….catch
一个异常的处理:
public class TryCatchDemo {
public static void main(String[] args) {
int a=10;
int b=0;
try{
System.out.println(a/b);
}catch(ArithmeticException ae){
System.out.println("除数不能为零");
}
System.out.println("over");
}
}
多个异常的处理:
int a=10;
int b=0;
int[] arr = {1,2,3};
try{
System.out.println(arr[3]);
System.out.println(a/b);
}catch(ArithmeticException ae){
System.out.println("除数不能为零");
}catch(ArrayIndexOutOfBoundsException ai){
System.out.println("数组越界");
}
System.out.println("over");
从上面的列子看到当使用try…catch时,它处理了除数不能为零和数组越界的错误,程序可以正常向下运行,打出over。
当处理多个异常时,只解决了数组越界的问题,即程序只走了try里的第一条语句。因为程序是从上向下运行的,在进行try里的语句时,它找到错误便与下面catch中相对应的异常相匹配,然后继续执行下面的程序。
有的时候我们可能并不清楚我们的语句的具体异常的类,我们可以使用catch(Exception e)来捕捉异常。
例如:
int a=10;
int b=0;
int[] arr = {1,2,3};
try{
System.out.println(arr[3]);
System.out.println(a/b);
System.out.println("abcdefg");
}catch(ArithmeticException ae){
System.out.println("除数不能为零");
}catch(ArrayIndexOutOfBoundsException ai){
System.out.println("数组越界");
}catch(Exception e){
System.out.println("出现错误了");//当上面的所有异常都没有和try里面的匹配时,程序一定会匹配此项。
}
上面的例子可供我们一定能捕捉到异常。但是我们最好清楚到底异常时属于哪一类的,Exception是应用层面上的最顶层的类,如果所有的错误我们都用来与这个匹配的话,会大大加大程序的运行时间,因为程序会在父类Exception下去寻找与错误相匹配的子类。且重要的一点是:Exception类一定要在子类的后面,否则程序不能通过
Throwable的几个常见方法
- getMessage() 返回此throwable的详细消息字符串
- toString() 返回此可抛出的简短描述
- printStackTrace() 将此throwable和其追溯打印到标准错误流
这些方法都可以在API中查到
例如:
int a=10;
int b=0;
try{
System.out.println(a/b);
}catch(ArithmeticException ae){
ae.printStackTrace();
}
System.out.println("over");
throws的方式处理异常
格式:
方法名+ throws+ 类名
有时候有的异常我们可以处理,但是有的时候由于权限限制我们处理不了或者我们不知道如何处理。throws就给我们提供了一种方式,将异常抛给了虚拟机。
例如:
public static void main(String[] args) throws ParseException {
method();
System.out.println("over over");
}
public static void method() throws ParseException {
String s = "2018-8-9";
SimpleDateFormat sdf = new SimpleDateFormat();
Date d = sdf. parse(s);
System.out.println(d);
}
结果如下:
这个结果比不是我们想要的,我们的目的是使程序能运行下去。
改进结果如下:
public static void main(String[] args){
try {
method();
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("over over");
}
//在方法声明上抛出,是为了告诉调用者我有问题
public static void method() throws ParseException {
String s = "2018-8-9";
SimpleDateFormat sdf = new SimpleDateFormat();
Date d = sdf. parse(s);
System.out.println(d);
}
throw的方式处理异常
throw是语句抛出一个异常,语法:throw(异常对象)
public static void main(String[] args) {
method();
}
public static void method(){
int a=10;
int b=0;
if(b==0){
throw new ArithmeticException();
}
else{
System.out.println(a/b);
}
System.out.println("over");
}
throws和throw的区别
throws:
用在方法后面,用的是异常类名。
可以跟多个异常类名,用逗号隔开。
表示抛出异常,让该方法的调用者来处理。
throws表示出现异常的一种可能性,不一定会出现这样的异常。throw
用在方法体内,跟的是异常对象名。
只能抛出一个异常对象名。
表示抛出异常,由方法体内的语句处理。
throw执行一定是抛出了某种异常。
finally
int a=10;
int b=0;
try {
System.out.println(a/b);
}catch(ArithmeticException ae){
System.out.println("除数不能为0");
}finally{
System.out.println("出错了");
}
可以看到finallyl里的语句是一定会执行的。
finally常用来处理java一些后续的工作.
在java的的finally首先必须使用在所有catch的最后位置,其次它是必须执行的,无条件执行,甚至即使前面的try-catch语句中已经存在异常了,它仍然会执行.
不管try语句块正常结束还是异常结束,finally语句块是保证要执行的.如果try语句块正常结束,那么在try语句块中的语句都执行完之后,再执行finally语句块.
异常的作用
在刚开始看异常这一块的时候,我特别不理解为什么会有异常这个东西,当编译或者运行时出错我们都可以通过提示来改动我们的代码使程序正常运行,当时异常给我的感觉就是它方便了我们偷懒,当有错误的时候我们可以通过处理异常的手段来逃避错误,使后续的程序正常运行。但是在学完后我觉得低昂一个程序员在写一个项目的时候总有我们解决不了的问题但是我们又想让程序正常运行,这个时候就需要异常处理,使程序正常运行,像我们用的qq、微信我们不可能让程序总是崩溃,异常在这里面就起了非常大的作用,