程序在运行过程中会因为很多原因导致程序出错,我们可以把可能会出现的错误用异常来表示,良好的try…catch会使我们的程序更加的健壮,所以优秀的代码离不开异常的处理

一丶异常的概念

在java中把导致程序中断运行的情况分为两种,一种就是异常,而另外一种叫做错误。所有异常的基类是Exception,错误的基类是Error。Exception是在java程序中可以编码进行控制的,具有可编程性,而Error是指Java运行时系统来显示与运行时系统本身有关的错误,Error对于程序员来说是灾难性的,程序无法控制,比如jvm堆栈溢出错误,操作系统分配内存错误等。不管是Exception还是Error,他们的共同父类是java.lang.Throwable(可抛出的) 类。

异常是指在程序运行期可能出现的非正常情况,这些情况将导致程序出错,这种出错不同于代码编写错误或程序算法出错,代码编写错误无法完成编译,而程序算法出错计算将取得错误的结果。程序出现异常时,缺省会直接造成程序的中断运行,提前预知这种异常的可能性可以补充异常处理的逻辑,从这个角度出发,异常也是一种行之有效的逻辑处理机制,在程序中声明异常或主动抛出异常也很常见。

简而言之,为了提高程序的健壮性,异常需要由程序员处理。

二丶异常的分类

java 警告 类型可能是基元 java异常的基类_System

 

 

1.Throwable

可抛出的,是异常的顶层父类,其他的异常或者错误都是Throwable的子类类型,只有是Throwable的体系类型,才可以使用异常的处理机制。

2.Error

称为错误,由JAVA虚拟机生成并抛出,包括动态链接失败、虚拟机异常等;程序对其不作处理

3.Exception

  1. 运行时异常: 都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
  2. 非运行时异常:是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。

三丶异常的处理格式和方法

 

java 警告 类型可能是基元 java异常的基类_java 警告 类型可能是基元_02

java 警告 类型可能是基元 java异常的基类_Test_03

1 try{
2 //可能出现异常的代码
3 }catch(可能出现异常的类型1 标识符){
4  //针对该异常的处理方式1
5 }catch(可能出现异常的类型2 标识符){
6  //针对该异常的处理方式2
7 }finally{
8  //最终执行的代码块
9 }

View Code

 

 

常用方法:
1、Throwable中的构造方法
Throwable():创建一个没有任何参数的异常对象
Throwable(String mes):创建一个带有指定消息的异常对象
Throwable(Throwable cause):创建一个有原因的异常对象

2、常用成员方法
getCause():获取异常对象中的原因异常
getMessage():获取异常详细的消息字符串
toString():返回此throwable的简短描述
printStackTrace():打印异常的调用栈轨迹

四丶异常的捕获和处理

 1、try{}catch{}捕捉异常

java 警告 类型可能是基元 java异常的基类_java 警告 类型可能是基元_02

java 警告 类型可能是基元 java异常的基类_Test_03

public class Test {
    public static void main(String[] args) {
        try{
            //可能会出现问题的程序
            int a [] = new int[5];
            a[10] = 10;
        }catch (ArrayIndexOutOfBoundsException e){
            //异常发生时的处理语句
            System.out.println("超出数组范围!");
        }finally {
            //这个代码块一定会被执行
            System.out.println("*****");
        }
        System.out.println("异常处理结束!");
    }
}

View Code

java 警告 类型可能是基元 java异常的基类_Code_06

 

 

可以看出,在异常捕捉的过程中要进行两个判断,第一是try程序块是否有异常产生,第二是产生的异常是否和catch()括号内想要捕捉的异常相同。

那么,如果出现的异常和catch()内想要捕捉的异常不相同时怎么办呢?事实上我们可以在一个try语句后跟上多个异常处理catch语句,来处理多种不同类型的异常。

java 警告 类型可能是基元 java异常的基类_java 警告 类型可能是基元_02

java 警告 类型可能是基元 java异常的基类_Test_03

1 public class Test {
 2     public static void main(String[] args) {
 3         try {
 4             //要检查的程序语句
 5             int a[] = new int[5];
 6             a[0] = 3;
 7             a[1] = 0;
 8             //a[1] = 0;//除数为0异常
 9             //a[10] = 7;//数组下标越界异常
10             int result = a[0]/a[1];
11             System.out.println(result);
12         } catch(ArrayIndexOutOfBoundsException ex) {
13             //异常发生时的处理语句
14             System.out.println("数组越界异常");
15             ex.printStackTrace();
16         } catch(ArithmeticException ex) {
17             System.out.println("算术运算异常");
18             //显示异常的堆栈跟踪信息
19             ex.printStackTrace();
20         } finally {
21             //这个代码块一定会被执行
22             System.out.println("finally语句不论是否有异常都会被执行。");
23         }
24         System.out.println("异常处理结束!");
25     }
26 }

View Code

java 警告 类型可能是基元 java异常的基类_Code_09

 

 上述例子中ex.printStackTrace();就是对异常类对象ex的使用,输出了详细的异常堆栈跟踪信息,包括异常的类型,异常发生在哪个包、哪个类、哪个方法以及异常发生的行号。

 2、声明并抛出异常

throws声明的方法表示该方法不处理异常,而由系统自动将所捕获的异常信息抛给上级调用方法。

java 警告 类型可能是基元 java异常的基类_java 警告 类型可能是基元_02

java 警告 类型可能是基元 java异常的基类_Test_03

1 public class Test {
 2     public static void main(String[] args) {
 3         int[] a = new int[5];
 4         try {
 5             setZero(a,10);
 6         } catch(ArrayIndexOutOfBoundsException ex) {
 7             System.out.println("数组越界错误!");
 8             System.out.println("异常:"+ex);
 9         }
10         System.out.println("main()方法结束。");
11     }
12     private static void setZero(int[] a,int index) throws ArrayIndexOutOfBoundsException {
13         a[index] = 0;
14     }
15 }

View Code

java 警告 类型可能是基元 java异常的基类_System_12

 3、自定义异常

throw的作用是手工抛出异常类的实例化,对象throw通常和throws联合使用,抛出的是程序中已经产生的异常类实例。

java 警告 类型可能是基元 java异常的基类_java 警告 类型可能是基元_02

java 警告 类型可能是基元 java异常的基类_Test_03

1 public class Test {
 2     public static void main(String[] args) {
 3 
 4         try{
 5             Test test = new Test();
 6             test.regist(-100);
 7 
 8         }catch(MyException e){
 9             System.out.println("异常:"+e);
10             e.printStackTrace();
11         }finally {
12             System.out.println("结束");
13         }
14     }
15 
16     public void regist(int num)throws  MyException{
17         if(num<0){
18             throw new MyException("人数为负值,不合理");
19         }
20         System.out.println("登记人数:"+num);
21     }
22 }

View Code

java 警告 类型可能是基元 java异常的基类_Code_15

 

 五丶异常处理总结

java 警告 类型可能是基元 java异常的基类_Code_16

 

 养成良好的编程习惯,不要把错误给吞噬掉(即捕获到异常以后又不做出相应处理的做法,这种做法相当于是把错误隐藏起来了,可实际上错误依然还是存在的), 也不要轻易地往外抛错误,能处理的一定要处理,不能处理的一定要往外抛。往外抛的方法有两种,一种是在知道异常的类型以后,方法声明时使用throws把 异常往外抛,另一种是手动往外抛,使用“throw+异常对象”你相当于是把这个异常对象抛出去了,然后在方法的声明写上要抛的那种异常。

java 警告 类型可能是基元 java异常的基类_Test_17