Java基础-Exception

来源:互联网 发布:暴雪游戏平台 mac版 编辑:程序博客网 时间:2024/06/04 18:25

Exception in thread “main” java.lang.ArithmeticException: / by zero

异常:程序出现了不正常情况
我们在编写程序的时候,可能会有很多的问题存在。为了将来方便的表示这些的问题的原因,类型,位置。java就提供了异常对象供我们使
用。

举例:
电脑键盘不灵。
原因:敲快了,进水了,线路坏了
解决方案:
A:敲快了–慢点敲
B:进水了–把水弄干
C:线路坏了—买个新的

异常体系:
超类:Throwable
|–Error:严重问题。通常是程序出现重大问题:运行的类不存在或者内存溢出等。是不需要处理的,一般这种情况需要修改代码
|–Exception:问题不严重
非运行时异常:(包括编译异常和其他异常)一般来说,我们只处理编译异常。
运行时异常:这个我们不需要处理,一般需要修改代码。

代码:

public class ExceptionDemo {    public static void main(String[] args) {        // 运行时期        int a = 10;        int b = 0;        System.out.println(a / b);        // 编译时期,报错        // FileInputStream fis = new FileInputStream("a.txt");    }}

这里写图片描述
因为这里出现了一个算术异常,我们都知道除数不能为0,Java针对这类算术异常,封装成一个ArithmeticException
通过查API发现,这个类继承自RunnableException这个类,所以是一个运行时异常,在编译期间不会报错,只有在程序运行过程中,才会报错。
这里写图片描述

如果程序中出现了问题,我们没有去处理,jvm会采用自动的处理方式:
该方式:jvm把异常的类型,原因,位置直接显示在了控制台。
这种方式有一个弊端:
弊端:当程序的某一个位置上出现异常,jvm处理完后,该位置一下的程序就没有执行的机会。

那么,在遇到程序有异常时,我们该怎么做?
A:编写处理代码:
基本格式:
try{
可能发生问题的地方
}catch(异常类名 变量名){
异常处理代码
}finaly{
//这里是一定会执行的代码,通常是一些释放资源的操作
}
B:在方法体上抛出该异常

当我们采用编写处理代码的方式处理异常时,即使程序在某处发生了异常,而我们已经处理了,所以,异常处代码下面的程序会继续执行,不会受其影响。
代码:

public class ExceptionDemo {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        System.out.println("请输入被除数:");        int a = sc.nextInt();        System.out.println("请输入除数:");        int b = sc.nextInt();        try {            int c = a / b;            System.out.println(c);        } catch (ArithmeticException ae) {            // 继续操作            // 返回一个错误页面            System.out.println("除数不能为0");        }        System.out.println("新年快乐");    }}

结果

从控制台输出可以看出,即使在 int c = a / b; 这里出现了问题,除数为0.。。。。程序最下面的 新年快乐 ,还是输出来了。

那么,如果一个代码中如果出现多种问题(多种异常),该如何解决呢?
A:每一个异常有可能出现的地方,都用一个try{}…catch(){} 来处理
B:针对所有可能出现异常的地方,使用一个try{}将所有地方都括起来,然后后面跟多个catch(){}语句,分别捕捉对应的异常类
格式:
try{
。。。。。。
}catch(){
。。。。。。
}catch(){
。。。。。。
}

注意:在异常处理中,一旦捕捉到异常,就会直接跳到对应的catch里面执行处理代码。不管异常发成处下方,是否还有其他语句,都不会执行,直接跳到catch里面。

方式A处理代码:

public class ExceptionDemo2 {    public static void main(String[] args) {         method1();    }    // 针对每一个异常写一个try...catch代码。    public static void method1() {        // ArithmeticException        int a = 10;        int b = 0;        try {            System.out.println(a / b);            System.out.println("hello");        } catch (ArithmeticException ae) {            System.out.println("除数不能为0");        }        // ArrayIndexOutOfBoundsException        int[] arr = { 1, 2, 3 };        try {            System.out.println(arr[3]);        } catch (ArrayIndexOutOfBoundsException ae) {            System.out.println("数组越界异常");        }        // 继续操作        System.out.println("over");    }}

结果

处理方式B代码:

public class ExceptionDemo2 {    public static void main(String[] args) {        method2();    }    public static void method2() {        try {            // ArithmeticException            int a = 10;            // int b = 0;            int b = 2;            System.out.println(a / b);            // ArrayIndexOutOfBoundsException 当上面捕获异常,下面的代码不会执行,因为上面并没有异常,所以这里的代码被执行            int[] arr = { 1, 2, 3 };            System.out.println(arr[3]);            // 不会被执行,因为上面已经捕获异常,直接跳到catch里面执行            System.out.println("over");        } catch (ArithmeticException ae) {            System.out.println("除数不能为0");        } catch (ArrayIndexOutOfBoundsException ae) {            System.out.println("数组越界异常");        }    }}

结果

注意:异常或者错误,都是以他们所在体系的父亲作为后缀。
XxxException
XxxError

针对多个异常,写一个try的代码,catch里面会不会有顺序问题呢?
如果异常是平级关系,没有顺序问题。
如果异常存在着子父关系,父一定要放在最后。
代码如下:

public class ExceptionDemo3 {    public static void main(String[] args) {        // method1();        // method2();        method3();    }    public static void method3() {        try {            // ArithmeticException            int a = 10;            // int b = 0;            int b = 2;            System.out.println(a / b);            // ArrayIndexOutOfBoundsException            int[] arr = { 1, 2, 3 };            // System.out.println(arr[3]);            System.out.println(arr[2]);            // 这里又出现了一个问题,这里很明显是一个空指针问题。            // 假设我们忘了,也就是说我们不知道这是一个什么异常。            // 怎么处理呢?            String s = null;            System.out.println(s.length());            // 继续操作            System.out.println("over");        } catch (Exception e) {            System.out.println("空指针问题");        }        // catch (ArrayIndexOutOfBoundsException ae) {        // System.out.println("数组越界异常");        // } catch (ArithmeticException ae) {        // System.out.println("除数不能为0");        // }    }    public static void method2() {        try {            // ArithmeticException            int a = 10;            // int b = 0;            int b = 2;            System.out.println(a / b);            // ArrayIndexOutOfBoundsException            int[] arr = { 1, 2, 3 };            // System.out.println(arr[3]);            System.out.println(arr[2]);            // 这里又出现了一个问题,这里很明显是一个空指针问题。            // 假设我们忘了,也就是说我们不知道这是一个什么异常。            // 怎么处理呢?            String s = null;            System.out.println(s.length());            // 继续操作            System.out.println("over");        } catch (Exception e) {            System.out.println("空指针问题");        }    }    public static void method1() {        try {            // ArithmeticException            int a = 10;            // int b = 0;            int b = 2;            System.out.println(a / b);            // ArrayIndexOutOfBoundsException            int[] arr = { 1, 2, 3 };            // System.out.println(arr[3]);            System.out.println(arr[2]);            // 这里又出现了一个问题,这里很明显是一个空指针问题。            // 假设我们忘了,也就是说我们不知道这是一个什么异常。            // 怎么处理呢?            String s = null;            System.out.println(s.length());            // 继续操作            System.out.println("over");        } catch (ArrayIndexOutOfBoundsException ae) {            System.out.println("数组越界异常");        } catch (ArithmeticException ae) {            System.out.println("除数不能为0");        } catch (Exception e) {            System.out.println("空指针问题");        }    }}

里面有三个方法,每一个方法,测试的是一种情况,method1方法中,把Exception放在了catch最后面,method2方法中,只使用了Exception类来接收收到异常;method3方法中,因为将Exception放在了catch的最前面,因此在其下面的两个子类,就不会被执行到,不注释掉会产生编译异常。

*JDK7新特性:多个catch用一个catch替代。 不是说多个catch的内容,用一个Exception处理。
格式:
catch(异常1 | 异常2 | 异常3 … 变量名){}*

代码如下:

public class ExceptionDemo4 {    public static void main(String[] args) {        // method();        method2();    }    private static void method2() {        try {            // ArithmeticException            int a = 10;            // int b = 0;            int b = 2;            System.out.println(a / b);            // ArrayIndexOutOfBoundsException            int[] arr = { 1, 2, 3 };            // System.out.println(arr[3]);            System.out.println(arr[2]);            // 这里又出现了一个问题,这里很明显是一个空指针问题。            // 假设我们忘了,也就是说我们不知道这是一个什么异常。            // 怎么处理呢?            String s = null;            System.out.println(s.length());            // 继续操作            System.out.println("over");        } catch (ArrayIndexOutOfBoundsException | ArithmeticException                | NullPointerException ae) {                //这里暂时输出一个语句                //当学习了printStackTrace()后,可以直接ae.printStackTrace();            System.out.println("这里出问题了");        }    }    private static void method() {        try {            // ArithmeticException            int a = 10;            // int b = 0;            int b = 2;            System.out.println(a / b);            // ArrayIndexOutOfBoundsException            int[] arr = { 1, 2, 3 };            // System.out.println(arr[3]);            System.out.println(arr[2]);            // 这里又出现了一个问题,这里很明显是一个空指针问题。            // 假设我们忘了,也就是说我们不知道这是一个什么异常。            // 怎么处理呢?            String s = null;            System.out.println(s.length());            // 继续操作            System.out.println("over");        } catch (ArrayIndexOutOfBoundsException ae) {            System.out.println("数组越界异常");        } catch (ArithmeticException ae) {            System.out.println("除数不能为0");        } catch (NullPointerException ne) {            System.out.println("空指针问题");        }    }}

Throwable中的方法:
A:public String getMessage():返回的是异常的消失字符串
B:public String toString():返回的是异常的简单描述信息
格式: 全路径名:消息字符串
C:public void printStackTrace():把错误的信息显示在控制台

方法A中的代码:
public class ExceptionDemo {    public static void main(String[] args) {        int a = 10;        int b = 0;        try {            System.out.println(a / b); // 一旦发生问题,在这里其实就产生了一个ArithmeticException对象。                                        // 然后,拿着这个对象,去和catch里面的类型进行匹配。如果有,就赋值。                                        // new ArithmeticException()        } catch (ArithmeticException ae) { // ArithmeticException ae = new                                            // ArithmeticException();            // System.out.println("除数不能为零");            // 通过分析,那么,ae是一个对象了            // / by zero             System.out.println(ae.getMessage());            // java.lang.ArithmeticException: / by zero             System.out.println(ae.toString());            // 实际开发中,会获取到异常后,自动判断是某种异常,然后一个错误信息处理界面。            ae.printStackTrace();        }        System.out.println("over");    }}

这里写图片描述

异常处理的完整代码:
格式:
try{
可能有问题的代码
}catch(异常类名 变量名){
处理方案。变量名.printStackTrace();
}finally{
释放资源。(数据库,IO)
}

finally:里面代码永远会执行。

代码:
public class FinallyDemo {    public static void main(String[] args) {        int a = 10;        int b = 0;        try {            System.out.println(a / b);        } catch (ArithmeticException ae) {            ae.printStackTrace();        } finally {            System.out.println("over");        }    }}
![这里写图片描述](http://img.blog.csdn.net/20150807002810723)    分析:  这里永远都会打印在finally里面的over

面试题:
2:finally里面的代码真的永远会执行吗?
* 会永远执行。但是有一个特殊情况:在代码执行到finally之前,jvm就退出了。
* 3:加入在catch里面有return语句,请问finally里面的代码还会执行吗?如果执行,是在return前,还是return后?
* 会执行。在return前执行。
* 准确答案:在return之间执行。

代码: 
public class FinallyTest {    public static void main(String[] args) {         method2();        int result = method3();        System.out.println(result);    }    private static int method3() {        int a = 10;        try {            System.out.println(a / 0);            System.out.println("a1:" + a);        } catch (ArithmeticException ae) {            System.out.println("a2:" + a); // a2:10            a = 20;            return a; //这个时候,在内存中就会有一个路径产生,该路径返回值是20.                      //但是,它看到了finally代码块,所以,继续执行finally里面的内容                             //当finally里面结束后,会回到以前的执行路径。        } finally {            System.out.println("a3:" + a); // a3:20            a = 30;            return a;         }//      return a;    }    private static void method2() {        int a = 10;        int b = 0;        try {            System.out.println(a / b);        } catch (ArithmeticException ae) {            ae.printStackTrace();            return;        } finally {            System.out.println("over");        }    }

结果

    分析:        上面打印出来的是method2方法调用时,printStackTrace()的信息        下面的都是method3方法调用时,输出的数值。。。这里面的值,说明了finally里面的语句一定会执行

Java中的自定义异常:

      java虽然已经考虑到了很多种异常情况,但是,有些需求java程序是考虑不到的。比如说:我要求学生的分数不能为负数。      那么,针对这种情况,我们就要编写自定义异常类进行处理。      如何编写一个自定义异常类呢?      就是自定义一个类,去继承Exception或者RuntimeException。      开发中:一般继承自RuntimeException。      我先讲Exception。自定义异常类MyException的代码如下:
public class MyException extends Exception {    public MyException(String message) {        super(message);    }}
使用异常类MyException的代码如下:
/* * 一旦你的判断需要做某些异常处理的时候, 你就应该在方法内部用throw关键字把该异常对象抛出。 * 格式: *      方法内部 *      throw 异常对象; */public class Teacher {    public void checkScore(int score) throws MyException {        if (score < 0 || score > 100) {            // System.out.println("分数错误");            MyException my = new MyException("分数不在指定范围内");            throw my;        } else {            System.out.println("分数正确");        }    }}
     测试类中的代码:
import java.util.Scanner;public class Test {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        System.out.println("请输入学生成绩:");        int score = sc.nextInt();        Teacher t = new Teacher();        try {            t.checkScore(score);        } catch (MyException e) {            System.out.println(e.getMessage());            // e.printStackTrace();        }        // t.checkScore(score);    }}
![这里写图片描述](http://img.blog.csdn.net/20150807004449743)结果分析:输入一个-1,会输出自定义异常里面定义好的信息message。
0 0
原创粉丝点击