Java异常

 异常

异常是程序执行时,出现的意想不到的情况导致你的程序无法正常运行

异常类的种类

(1)java.lang.Throwable类是Java程序执行过程中发生的异常时间对应类的父类

(2)Throwable可分为两类:Error(错误)和Exception(异常)

Error:Java虚拟机无法解决的严重问题。比如JVM系统内部错误,资源耗尽,程序员是没有办法解决的。如StackOverflowError(栈内存溢出)和OutOfMemoryError(堆内存溢出)

②Exception:因编程错误或偶然的外在因素导致的一般性问题。需要针对性的代码进行处理,使程序继续运行

例如:

  -空指针异常

    -文件找不到异常

    -数组角标越界

(3) 异常分为:编译时异常和运行时异常

编译时异常:再执行javac.exe命令时,出现的异常,需要在编译时进行解决的异常

例如:

  -ClassNotFoundException:类找不到异常

  -FileNotFoundException   :文件找不到异常

  -IOException                     :输入输出异常

运行时异常:在执行javac.exe命令时,运行时出现的异常

  -ArrayIndexOutOfBoundsException:数组越界异常

  -NullPointerException                      :空指针异常

  -ClassCastException                       :类型转换异常

  -NumberFormatException               :数字格式异常

  -ArithmeticException                       :算数异常

为什么要使用异常处理?

因为当你捕获到异常并将异常处理后程序仍能正常执行,所以异常的处理可以极大提高程序的健壮性

举个例子:

1 public class Test {
2     public static void main(String[] args) {
3         System.out.println("开始运算");
4         int a=10;
5         int b=0;
6         System.out.println("a/b的值:"+a/b);
7         System.out.println("运算结束");
8     }
9 }

效果展示:

发现当我第6行出现算术异常的时候,程序会立刻终止,连后面的输出语句不会执行,这就是一种异常

 如何处理异常

异常的处理Java中存在两种方法,①try.....catch.......finally②throws

①try......catch.......finally

语法:

try{
   //可能出现异常的代码内容
}catch(异常类型1    异常对象){
   //异常处理方法
}catch(异常类型n    异常对象){
    //异常处理方法
}finally{
    //无论是否有异常都会执行的内容
}

举个例子:

 1 public class Test {
 2     public static void main(String[] args) {
 3         System.out.println("开始运算");
 4         try {
 5             int a=10;
 6             int b=0;
 7             int c=a/b;
 8             System.out.println("运算的结果为:"+c);
 9         } catch (ArithmeticException e) {
10             System.out.println("异常正在处理......异常处理完毕");
11         }
12         System.out.println("运算结束");
13     }
14 }

效果展示:

 当try代码中可能出现的异常用catch来捕获,捕获成功处理后,代码可以重新正常执行,不会终止。

异常处理的原理

原理图展示:

一个try语句可以有多个catch语句,当异常产生时,由catch语句进行捕捉,catch语句会先匹配第一个异常类型如果匹配不上匹配第二个以此类推如果都不匹配上,将由JVM处理异常,JVM会打印出错误日志并终止程序。如果匹配上某一个catch语句后,后续的catch不再执行只会执行catch后面的代码

finally语句

无论程序是否存在异常都会执行finally语句里的代码常用来执行关闭连接关闭文件资源释放线程等操作。

举个例子:

①代码中没有出现异常的时候:

代码:

 1 public class Test {
 2     public static void main(String[] args) {
 3         System.out.println("开始运算");
 4         try {
 5             //程序没有异常的时候
 6             int a=10;
 7             int b=2;
 8             int c=a/b;
 9             System.out.println("运算的结果为:"+c);
10         } catch (ArithmeticException e) {
11             System.out.println("异常正在处理......异常处理完毕");
12         }finally {
13             //因为没有写资源流,这里用输出语句来代替
14             System.out.println("资源流的关闭");
15         }
16         System.out.println("运算结束");
17     }
18 }

效果展示:

②出现异常的时候:

代码:

 1 public class Test {
 2     public static void main(String[] args) {
 3         System.out.println("开始运算");
 4         try {
 5             //程序没有异常的时候
 6             int a=10;
 7             int b=0;
 8             int c=a/b;
 9             System.out.println("运算的结果为:"+c);
10         } catch (ArithmeticException e) {
11             System.out.println("异常正在处理......异常处理完毕");
12         }finally {
13             //因为没有写资源流,这里用输出语句来代替
14             System.out.println("资源流的关闭");
15         }
16         System.out.println("运算结束");
17     }
18 }

效果展示:

可以看出来无论程序是否出现异常,都会执行finally中的代码块。

②throws抛出异常

异常进行抛出去,让调用者来解决异常,这个也算是一个对异常的处理方式。

语法:

修饰符    返回类型    方法名(参数列表)  throws 异常列表{
         //方法体
}

举个例子:

1 public void multiply() throws ArithmeticException{
2         System.out.println("开始运算");
3         int a=5;
4         int b=0;
5         int c=a/b;
6         System.out.println("运行结果:"+c);
7         System.out.println("算术运算");
8}

声明这个方法可能存在算术异常,让调用者来处理这个异常,调用者可以使用try....catch...finally处理或同样throws抛出去。

开发中,如何选择异常处理的两种方式?

①如果程序代码中,涉及到资源调用(流,数据库连接,网络连接等),则必须考虑使用try-catch-finally来处理保证不出现内存泄露

②如果父类被重写的方法没有throws异常类型,则子类重写的方法中如果出现异常,只能考虑用try-catch进行处理,不能throws。

③开发中,方法 a 中依次调用方法 b,c,d 等方法方法 b,c,d 之间是递进关系。此时,如果方法 b,c,d 中有异常我们通常选择使用 throws ,而方法a通常选择使用try-catch-finally 

throw生成异常对象

Java允许程序员自己手动生成一个异常对象,比如在给类属性赋值的时候如果用户输入不合法则需要生成一个异常来提高代码的健壮性

语法:

throw new  异常类型(异常信息)

举个例子:

 1 public class Test {
 2     public static void main(String[] args) {
 3         System.out.println("开始运算");
 4         try {
 5             //自己手动生成一个异常
 6             throw new RuntimeException("手动生成异常");
 7             //System.out.println();  
 8             //由于已经手动生成异常对象,后面的代码是不能执行的,所以生成异常后面不允许有代码
 9         } catch (ArithmeticException e) {
10             System.out.println("异常正在处理......异常处理完毕");
11         }finally {
12             //因为没有写资源流,这里用输出语句来代替
13             System.out.println("资源流的关闭");
14         }
15         System.out.println("运算结束");
16     }
17 }

效果展示:

因为我生成的异常是RuntimeException异常,catch中的异常类型不与它匹配所以无法处理,只能交给JVM处理,JVM会打印日志并终止程序。

这里需要注意一点:手动生成异常后面不能有任何的代码内容

自定义异常

为什么需要自定义异常?

Java已经提供了丰富的异常类,而我们想要自定义异常主要是想通过异常的名字就可以直接判断这个是什么异常

这样我们就有必要在实际开发场景中自定义异常让我们可以起到见名知意的效果。

如何自定义异常类?

①继承于现有的异常体系。通过继承于:RuntimeException\Exception

②提供一个或多个构造器

语法:

class  自定义异常名    extends   现有的异常类{
            //提供构造方法
        public   自定义异常名(形参列表){
            //调用父类的构造方法
        }    
}        

举个例子:

 1 public class Test {
 2     public static void main(String[] args) {
 3         try {
 4             //生成一个自定义异常类对象
 5             throw new PasswordErrorException("密码错误");
 6         }catch (RuntimeException e){
 7             //打印出异常信息
 8             System.out.println(e.getMessage());
 9         }
10        
11     }
12 }
13 //生成一个自定义异常类
14 class PasswordErrorException extends RuntimeException{
15     //提供一个构造器,继承父类的构造方法
16     public PasswordErrorException(String msg){
17         super(msg);
18     }
19     
20 }

效果展示:

生成的异常类对象被捕捉后,打印出异常的信息。

 

posted @ 2023-11-13 11:30  和哗  阅读(8)  评论(0编辑  收藏  举报