java 中的异常处理

1、什么是异常怎么处理异常

两个数相除的小代码会遇到三个问题

  • 参数个数不对 java.lang.ArrayIndexOutOfBoundsException
  • 参数类型不对 java.lang.NumberFormatException
  • 被除数为零 java.lang.ArithmeticException

对这些问题的处理如下

public class ExceptionDemo {
    public static void main(String args[]) {
        System.out.println("---------计算开始---------");
        try { //在这里捕捉异常,将其与 catch 括号中的异常进行配对,配上了就跳出 try ,直接执行 catch 里的内容
            String str1 = args[0];
            String str2 = args[1];
            int i = Integer.parseInt(str1);
            int j = Integer.parseInt(str2);
            int temp = i /j;
            System.out.println("两个数相除的结果是:"+temp);
        }catch(ArithmeticException e) {//被除数为0,算术问题匹配对象
            //System.out.println("算术异常:"+e);
            e.printStackTrace();
        }catch(NumberFormatException e){//用户输入的不是数字,数字类型匹配对象
            System.out.println("数字转换异常:"+e);
        }catch(ArrayIndexOutOfBoundsException e){//用户输入的数字个数不对
            System.out.println("数组越界异常:"+e);
        }finally { //不管有没有匹配的异常对象都输出这个
            System.out.println("处理完成");
        }
        System.out.println("---------计算开始---------");
    }
}

2、异常类的继承结构

  • 前面接触到了三个异常:ArithmeticException、NumberFormatException、ArrayIndexOutOfBoundsException
    注意
以上三个类都是继承了 java.lang.Exception 类
而 Exception 类继承了 Throwable 类
Throwable 类有两个子类 Error、Exception
Exception:一般表示的是程序中出现的问题,可以直接使用 try...catch 处理。
Error:一般指的是 JVM 错误,程序中无法处理。如执行 java A
一般将 Exception 与 Error 统称为异常,前面的三个异常类都是继承 Exception 类。
可以使用 System.out.println(); 方法输出异常
也可以在 Exception 的子类  AclNotFoundException 中找到  printStackTrace() 方法,该方法可以进行输出

3、异常的处理机制

**整个java处理异常中,应用了java的多态性

  • 一旦产生异常,会在 try 中捕捉异常创建一个异常类的实例化对象
  • 将捕捉到的异常对象与 catch 语句中的各个异常类型进行匹配,如果配对成功就执行 catch 里的代码

多态* 子类的实例化对象可以直接使用父类的对象进行接收。
所有的异常类都是 Exception 的子类,所以所有的异常对象都可以用 Exception 进行接收。
因为程序的顺序执行,所以 Exception 的捕捉要放在最后:
在异常处理中,捕获更粗的异常要放在捕获更细的异常之后

...
catch(Exception e){
    e.printStackTrace();
}
...

如果所有异常的处理方式一样,可以只用 Exception 来捕获,这属于“偷工减料”
问题:
直接使用 Exception 捕获异常简单粗暴,那能不能用 Exception 的父类 Throwable 进行捕获呢?
答:是可以捕获的,但是 Throwable 有两个子类 Exception 和 Error ,程序在运行中只会抛出 Exception 的子类,这么做的话目的不够明确。

4、throws 与 throw 关键字

1、定义一个方法时可以用 throws 关键字声明,表示此方法不处理异常,交异常给方法调用处进行处理。

class Math {
    public int div(int i,int j)throws Exception {//throws 关键字声明方法,抛出异常
        int temp = i/j ;
        return temp ;
    }
}

public class ThrowsDemo {
    public static void main(String args[]) {
        Math math = new Math();
        try {
            System.out.println("两个数相除结果:"+math.div(10, 2));
        }catch(Exception e) {
            e.printStackTrace();
        }
        }
}

主方法也可以抛出异常而不处理,这种情况是交给 JVM 处理,出现异常将导致程序中断
2、throw 关键字是用来人为的手工抛出异常的

public class ThrowDemo {
    public static void main(String args[]) {
        try {
            throw new Exception("自己抛出异常");
        }catch(Exception e) {
            e.printStackTrace();
        }
    }
}

5、在开发中,一般都是将 try...catch...finaly、throw、throws 综合起来使用的。

设计一个相除的方法  
要求必须打印“计算开始”、“计算结束”信息  
如果有异常刚交给调用处处理  
//开发模式一般会这样使用异常处理
class Mathadd{
    public int div(int i,int j)throws Exception {
        System.out.println("**** 计算开始 ****");
        int temp = 0 ;  
        try{
            temp = i/j ;
        }catch(Exception e){
            throw e ; //抛出异常给调用处处理
        }finally { 
            // 不管是否有异常都执行的统一出口,
            // 在开发中经常使用,释放资源或者是干嘛
            System.out.println("**** 计算结束 ****");
        }
        return temp ;
    }
}
public class TryThrowDemo {
    public static void main(String args[]) {
        Mathadd mathadd = new Mathadd() ;
        try {
            System.out.println("除法操作:"+mathadd.div(10, 0));
        }catch(Exception e) {
            System.out.println("异常产生:"+e);
            //e.printStackTrace();
        }
    }
}

6、Exception 类与 RuntimeException 类的区别

以下代码用到了 Integer 类下的 parseInt() 方法,查看文档中该方法

public class RuntimeExceptionDemo {
    public static void main(String args[]) {
        String string = "123" ;
        int temp = Integer.parseInt(string) ;
        System.out.println("乘方操作:"+(temp*temp));
    }
}

Integer 类在 java.lang 包中
parseInt() 方法的定义如下
public static int parseInt(String s) throws NumberFormatException
该方法使用了 throws 关键字抛出了异常,但是在以上代码中使用的时候并没有处理异常。
再看看 NumberFormatException 异常类,可以发现其是 RuntimeException 的孙类。
所以如果抛出的是 RuntimeException 的子类的异常可以不用处理,处理机制直接交给JVM处理了

7、自定义异常

自定义的异常只要继承 Exception 类即可

class MyException extends Exception {
    public MyException(String msg) {
        super(msg) ;
    }
}
public class DefaultException {
    public static void main(String args[]) {
        try {
            throw new MyException("自己定义的异常") ;
        }catch (Exception e) {
            System.out.println(e);
        }
    }
}

8、断言

断言是假设一个执行结果,如果实际执行结果不对就返回错误

public class Test {
    public static void main(String args[]) {
        int x[] = {1,2,3} ; //定义一个长度为3的整型数组 
        assert x.length == 0 : "数组的长度不为0"; //此处断言数组的长度为0并且作出错误提示
    }
}

在 eclipse 中执行,如果没有设置,断言是不会起效果的。
在黑窗口中执行,让断言起效果的方式是java -ea Test 或者java -enableassertions Test

  • 虽然断言返回的是 boolean 值,但是不能作为条件判断语句
  • 不提倡过多使用断言

9、小结

1、异常出现之后,如果没有进行处理,则会让整个程序中断执行。
2、使用 try...catch 和 try...catch...finally 可以处理异常,finally 将作为异常的统一出口。
3、一个异常处理中可以同时出现多个 catch ,但是捕获更粗的异常要放在捕获更细的异常之后。
4、在异常中最大的类是 Throwbale ,分为两个子类:Exception、Error

  • Exception 是程序可以自己处理的异常。
  • Error 是 JVM 错误,一般程序无法处理。

5、处理异常可以直接用 Exception ,但是最好分开各个异常捕获处理,不要偷工减料。
6、产生异常,会在 try 中实例化一个异常的对象,此对象与 catch 中声明的对象类型进行匹配,匹配成功就执行 catch 中的代码,如果 一直无法匹配成功,则程序中断。
7、throws 与 throw 的区别

  • throws 在方法声明时使用,抛出异常给方法调用处处理。
  • throw 是人为地抛出异常。

8、Exception 与 RuntimeException 的区别

  • Exception 一定要对其抛出的异常处理。
  • RuntimeException 可以不对其抛出的异常处理,建议要处理。

9、在开发中处理异常一般都将 try...catch...finaly、throws、throw 用上。
10、自定义异常只需要继承 Exception 或其子类即可。
11、断言不太重要。

你可能感兴趣的:(java 中的异常处理)