javaday21_异常(自定义异常)

异常:

异常的继承体系:

Throwable 在java.lang中。

Throwable 是所有错误或异常的超类,所以它下面有两个大的子类---Error错误类,---Exception异常类。(我们平时不会关心错误,而是关心异常类。)

Throwable(类) <--Exception (类)

        <--Error (类)        

Error 和 Exception 的区别:

什么是错误,什么是异常呢?

Error 一般都是大问题,例如,开辟的内存过大之类,这样的一般都要修改代码!

Exception  一般都是小问题,例如,数组越界之类的,这样的一般将异常处理掉就可以了。

错误在运行的时候才会发生。

Exception 异常,的解决方法是:将异常处理掉,就可以了。

Error 错误,的解决方法是: 修改程序。 

所以,我们一般处理的也都是异常,如果是Error 就只能改代码了。

在Exception异常 下面还有个子类 --RuntimeException 类。

我们主要说 Exception 和 RuntimeException !

异常对象的产生原因 和 处理方式:

如果最终 main 到了 JVM  的话,

它又做了两件事

1,将异常信息,以红色字体输出到控制台。 

2,将程序停止结束。  

如果在这个过程中,有人处理 这个异常的话,就不会出现抛到上一级的情况,那么代码也就可以继续执行了。

注: 当抛出到上一级的时候,剩余的程序都不会再执行了

方法内部抛出异常的 关键字 throw :

抛出的对象,必须是Exception 或者 它的子类对象。  

 1 package cn.zcb.demo04;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         int arr[] = {1,2,3};
 6         int a = getNum(arr);
 7         System.out.println(a);
 8 
 9     }
10     public static int getNum(int []arr){
11         if(arr == null){
12             throw new Exception("传递的数组不存在");
13         }
14         if(arr.length == 0){
15             throw new Exception("数组中为任何元素");
16          }
17         int ret = arr[3];
18         return ret;
19     }
20 
21 
22 }
使用throw来抛出异常!

此时的程序还是有bug 的。继续看下面:

声明异常的 关键字 throws

上面的throw + 对象是用来抛出异常的。

这里的throws是用来写在方法的声明上的。声明此方法可能会出现异常。

当调用者调用一个可能出现异常的方法的时候,它就必须处理该异常,如果不处理就会编译失败!

例如:

 1 package cn.zcb.demo04;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         int arr[] = {1,2,3};
 6         int a = getNum(arr);//此时main 调用了可能出现异常的方法getNum,但是却没有处理该异常。于是就编译失败了!
 7         System.out.println(a);
 8 
 9     }
10     public static int getNum(int []arr) throws Exception{
11         if(arr == null){
12             throw new Exception("传递的数组不存在");
13         }
14         if(arr.length == 0){
15             throw new Exception("数组中为任何元素");
16          }
17         int ret = arr[3];
18         return ret;
19     }
20 
21 
22 }
调用者不处理异常,就出现编译失败了。

注:Exception 类的异常必须要声明异常,但是RuntimeException及其子类不用声明异常

异常的处理方式 try -catch-finally :

之前,遇到异常都是一个字:往上抛,最后抛给了JVM,然后程序就终止了。

下面我们使用异常的另一个  处理方式 try -catch!

catch 中执行之后,就是处理了异常了,就不会往上面抛了。

注:finally 是一定会执行的。

异常的处理方式 多catch 捕获:

指的是调用的方法可能有多个 异常产生,这时可以用多个catch 。

 1 package cn.zcb.demo05;
 2 
 3 public class Test {
 4     public static void main(String[] args){
 5 //        int arr[] = null;
 6         int arr[] = new int[0];
 7         try {
 8             int a = getNum(arr);
 9             System.out.println(a);
10         }catch (NullPointerException e){
11             System.out.println(e);
12         }catch (ArrayIndexOutOfBoundsException e){
13             System.out.println(e);
14         }
15     }
16     public static int getNum(int []arr)throws NullPointerException,ArrayIndexOutOfBoundsException {
17         //因为传来的参数是 引用类型,因此肯定要判断是否为空
18         if(arr == null){
19             throw new NullPointerException("数组不存在!");
20         }
21         if(arr.length <=3){
22             throw new ArrayIndexOutOfBoundsException("数组没有3索引");
23         }
24 
25         int ret = arr[3];
26         return ret;
27     }
28 
29 
30 }
View Code

catch() 的顺序:

1,平级之间的异常( 例如NullPointerException 和 NoSuchElementExceptino 和 ArrayIndexOfBoundsException):

平级之间,书写是可以没有顺序的。

2,有继承关系的异常(NullPointerException 和 Exception):

平级之间,书写是有顺序的。

高级应该写在下面。

它的原因是多态调用。 如果将Exception写在上面的话,那么下面的异常就永远也起不到作用了!

关于 try-except-finally 中的finally :

 1 package cn.zcb.demo05;
 2 
 3 public class Test {
 4     public static void main(String[] args){
 5         try {
 6             func(0); //产生异常
 7 //            func(1);//不产生异常!
 8         }catch (Exception e){
 9             System.out.println(e);
10         }finally {
11             System.out.println("无论产生异常与否,我是一定会被执行的“");
12         }
13 
14 
15     }
16     public static void func(int a) throws Exception{
17         if( a == 0){
18             throw new Exception("异常产生");
19         }
20     }
21 
22 }
View Code

finally 只有一种情况不执行,就是用代码将 JVM 停止:System.exit(0);  

 1 package cn.zcb.demo05;
 2 
 3 public class Test {
 4     public static void main(String[] args){
 5         try {
 6 //            func(0); //产生异常
 7             func(1);//不产生异常!
 8             System.exit(0);
 9 
10         }catch (Exception e){
11             System.out.println(e);
12             System.exit(0);
13         }finally {
14             System.out.println("无论产生异常与否,我是一定会被执行的“");
15         }
16 
17 
18     }
19     public static void func(int a) throws Exception{
20         if( a == 0){
21             throw new Exception("异常产生");
22         }
23     }
24 
25 }
费尽心机,就是为了使finally 不执行。哈哈哈

总结:一般finally 都是一定执行的,无论异常产生与否,除非你刻意不让它执行!

那么finally 的作用是什么呢?它可以释放资源! 后面IO流中会有涉及!

try-catch 和 throws 两种处理方式:

调用者调用一个可能产生异常的方法的时候,它必须要做出处理,

它有两种选择,

一是不管它,在自己函数声明的地方加上throws,这时,如果产生异常,异常会自动的抛给上一级,最后到JVM。

二是使用try-catch ,它会处理异常,然后继续执行程序。

 1 package cn.zcb.demo05;
 2 
 3 public class Test {
 4     public static void main(String[] args) throws Exception{
 5         func_P();
 6     }
 7     public static void func_P() throws Exception{
 8         func(0);
 9     }
10     public static void func(int a) throws Exception{
11         if( a == 0){
12             throw new Exception("异常产生");
13         }
14     }
15 }
对于异常,使用throws处理方式!
 1 package cn.zcb.demo05;
 2 
 3 public class Test {
 4     public static void main(String[] args){
 5         func_P();
 6     }
 7     public static void func_P() {
 8         try {
 9             func(0);
10         }catch (Exception e){
11             System.out.println(e);
12         }
13     }
14     public static void func(int a) throws Exception{
15         if( a == 0){
16             throw new Exception("异常产生");
17         }
18     }
19 }
try-catch 处理异常方式!

下面代码比上面好,下面代码不会终止程序,而上面代码会终止程序!

因此处理异常,我们应该使用try-catch !

注意:

对于可能会产生异常的方法,对于Exception 异常,方法自己  必须要声明该异常,但是对于RuntimeException 及其子类的异常,可以不声明!!!

异常 分类:

异常分为 编译时异常 运行时异常!!!

运行时异常 指的是 RuntimeException 类及其 子类 ,其他的基本都是编译时异常。

补:异常的继承关系:

Throwable(类) <--Exception (类) <- RuntimeException 类。

        <--Error (类)       

运行时异常是不需要进行 throws语句声明的!即我们前面说的----对于RuntimeException 及其子类,可以不进行throws声明。

调用也不需要对其处理,

具体代码如下:

 1 package cn.zcb.demo05;
 2 
 3 public class Test {
 4     public static void main(String[] args){
 5         func(0); //2 调用者也不需要进行处理 !
 6     }
 7     public static void func(int a){  //1,这不需要写 throws声明语句!
 8         if( a == 0){
 9             throw new RuntimeException("异常产生");
10         }
11     }
12 }
View Code

那么,它这样设计的目的是什么呢?

是因为运行异常本身,就不能发生,这时候要做的是停止程序,修改源代码。

因为运行异常一旦发生,后面的代码在执行是没有意义的。

运行时异常就是让程序人员停下来改代码的。

它和其他的异常都不太一样!

运行时异常和 其他异常的区别:

 1 package cn.zcb.demo05;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         try{
 6             func(0);
 7         }catch (Exception e){
 8             e.printStackTrace();
 9         }
10     }
11     public static int func(int a) throws Exception{
12         if(a == 0){
13             throw new Exception("异常!");
14         }
15         return  0;
16     }
17 }
18 /*
19 * 一般异常 输出
20 java.lang.Exception: 异常!
21     at cn.zcb.demo05.Test.func(Test.java:13)
22     at cn.zcb.demo05.Test.main(Test.java:6)
23 
24 Process finished with exit code 0
25 * */
非运行时异常,exit 码为0 ,程序和正常返回
 1 package cn.zcb.demo05;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         func(0 );  //调用者不需要进行 try catch  !!!
 6     }
 7     public static int func(int a) {
 8         if(a == 0){
 9             throw new RuntimeException("异常!");
10         }
11         return  0;
12     }
13 }
14 /*
15 * 运行时异常 输出
16 Exception in thread "main" java.lang.RuntimeException: 异常!
17     at cn.zcb.demo05.Test.func(Test.java:9)
18     at cn.zcb.demo05.Test.main(Test.java:5)
19 
20 Process finished with exit code 1
21 * */
运行时异常,exit 返回 1

子类重写父类的方法 的异常问题:

总结:

一句话:父类抛了(声明)异常,子类可以抛(声明)但不能抛(声明)过头;父类没有(声明)抛,子类永远不能(声明)抛。

异常和错误 的超类 ---Throwable 类  的三个方法:

这三个方法都是和 “信息” 有关系,这个“信息” 是指的是 出现在输出框中的红色字!

String getMessage();  //对异常信息的简短描述

String toString();  对异常信息的详细描述

void printStackTrace();  //将异常信息 追踪到标准的 错误流 ! 异常信息是最详细的(也是JVM默认的调用方法!)。

 1 package cn.zcb.demo05;
 2 
 3 public class Test {
 4     public static void main(String[] args){
 5         try {
 6             func(0);
 7         }catch (Exception e){
 8             System.out.println(e.getMessage()); //简短异常信息
 9             System.out.println(e.toString()); //异常信息 详细描述 !相对上面 有了具体哪个类
10             e.printStackTrace(); //异常信息,最详细!  
11         }
12 
13     }
14     public static void func(int a) throws Exception{
15         if( a == 0){
16             throw new Exception("异常产生");
17         }
18     }
19 }
View Code

自定义异常:

 1 package cn.zcb.demo05;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         int avg = getAvg(10,20,30,40);
 6         System.out.println(avg);
 7 
 8     }
 9     /**
10      * 当计算成绩时候,如果传递是 负数,应该停止再计算了!  需要抛出异常!
11      * 但是,由于Java 中没有现成的 关于负数的异常,所以我们自定义异常!
12      */
13     public static int getAvg(int ...score){
14         int sum = 0;
15         for (int s:score){
16             sum+= s;
17         }
18         return sum/score.length;
19     }
20 }
View Code
 1 package cn.zcb.demo05;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         int res = getAvg(10,20,30,40,-10);
 6         System.out.println(res);
 7 
 8     }
 9     public static int getAvg(int...scores){
10         int sum = 0;
11         for (int score:scores){
12             if(score <0 ){
13                 throw new MyException("负数异常,成绩不能为负数!");
14             }
15             sum += score;
16         }
17         return sum/scores.length;
18     }
19 }
Test.java
package cn.zcb.demo05;

//关于 负数的异常,它比较适合使用 RuntimeException 异常,
//它只要是有 负数,我就直接把 你的程序给你停止(exit 码非0)了!
public class MyException extends RuntimeException {
    //必须要 继承(继承Throwable 或其子类!),因为这样才会有可抛性!
    public MyException(){};
    public MyException(String s){}

}
MyException.java

此时的问题是 当异常产生时候,没有输出 我们new 时候的String。

上面也说了,我们这时候应该将这个参数传给super() ,传给上一级,它会一级一级的传,最后是在超类 Throwable中最终将这个字符串 输出到控制台!

代码最终如下:

 1 package cn.zcb.demo05;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         int res = getAvg(10,20,30,40,-10);
 6         System.out.println(res);
 7 
 8     }
 9     public static int getAvg(int...scores){
10         int sum = 0;
11         for (int score:scores){
12             if(score <0 ){
13                 throw new MyException("负数异常,成绩不能为负数!");
14             }
15             sum += score;
16         }
17         return sum/scores.length;
18     }
19 }
Test.java
 1 package cn.zcb.demo05;
 2 
 3 //关于 负数的异常,它比较适合使用 RuntimeException 异常,
 4 //它只要是有 负数,我就直接把 你的程序给你停止(exit 码非0)了!
 5 public class MyException extends RuntimeException {
 6     //必须要 继承(继承Throwable 或其子类!),因为这样才会有可抛性!
 7     public MyException(){
 8         super();
 9     }
10     public MyException(String s){
11         super(s);
12     }
13 
14 }
MyException.java

注:大部分的异常都是 RuntimeException 异常!

当然,也可以不自定义异常,如下代码:

 1 package cn.zcb.demo05;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         int res = getAvg(10,20,30,40,-10);
 6         System.out.println(res);
 7 
 8     }
 9     public static int getAvg(int...scores){
10         int sum = 0;
11         for (int score:scores){
12             if(score <0 ){
13                 throw new RuntimeException("负数异常,成绩不能为负数!");
14             }
15             sum += score;
16         }
17         return sum/scores.length;
18     }
19 }
View Code
原文地址:https://www.cnblogs.com/zach0812/p/11915578.html