java学习笔记(八)-- 异常

异常体系图

  • Error:描述Java运行时内部错误与资源耗尽错误(OOM,StackOverflow)应用程序不抛出此类异常。这种内部错误一旦出现,除了告知用户并使用安全终止之外,再无能为力。
  • Exception(程序本身错误):Java应用程序抛出异常。
  • IOException:程序本身没有问题,由于IO处理导致的程序出错。
  • RuntimeExcpetion:运行时异常

关于受查异常和非受查异常

  • 非受查异常(无须强制处理):所有继承于Error或RuntimeException的异常类称为非受查异常(运行时异常)。比如:NullPointerException,ClassCastException,ArrayIndexsOutOfBoundsException,ArithmeticException(算术异常,除0溢出)
  • 受查异常(调用处必须强制处理):所有继承于Exception与IOException的类称为受查异常(编译器异常)比如:Exception,FileNotFoundException,IOException,SQLException.

异常处理格式:

try{
    可能出现异常的语句(error类)
}[catch(异常类 对象)]{
    出异常的操作          (Exception类)
}[finally]{
    异常出口
}
try...catch
try...finally
try...catch...finally...

范例·:当你知道产生异常的原因,位置,可以直接输出异常类对象,或者调用所有异常类中提供的printStackTrace()方法进行完整异常信息的输出。

public class Test {
    public static void main(String[] args) {
        System.out.println("1.数学计算开始前");
        //产生异常
        System.out.println("2.数学计算:"+10/0);
        System.out.println("3.数学计算结束后");
    }
}
//数字除零异常
//ArithmeticException

异常处理:使用try...catch...

public class Test {
    public static void main(String[] args) {
        System.out.println("1.数学计算开始前");
        //处理产生异常
        try {
        System.out.println("2.数学计算:"+10/0);
        } catch (ArithmeticException e) {
            System.out.println("异常已经被处理");    
            //e.printStackTrace();  打印异常错误堆栈
        }
        System.out.println("3.数学计算结束后");
    }
}
/*
1.数学计算开始前
异常已经被处理
3.数学计算结束后
*/

异常处理:使用try...catch...finally

public class Test {
    public static void main(String[] args) {
        System.out.println("1.数学计算开始前");
        //处理产生异常
        try {
            System.out.println("2.数学计算:" + 10 / 0);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        } finally {
            System.out.println("[finally]不论是否产生异常,都执行此句");
        }
        System.out.println("3.数学计算结束后");
    }
}
/*
1.1.数学计算开始前
java.lang.ArithmeticException: / by zero
at www.Dyson.java.Test.main(Test.java:8)
[finally]不论是否产生异常,都执行此句
3.数学计算结束后
*/

**** 重要 ****

范例:关于finally执行顺序问题,最终返回值问题   在JVM执行finally块中的return会覆盖之前的return

public class Test{
    public static void main(String[] args) {
        System.out.println(test());
    }
    public static int test(){
        try {
            System.out.println("try块....");
            return 1;
        } catch (Exception e) {
            System.out.println("catch块....");
            return 2;
        } finally {
            System.out.println("finally块....");
            return 3;
        }
    }
}
/*
finally是必执行,不会因为前面的return而提前返回
try块....
finally块....
3
*/

范例:初始化参数进行数学运算

public class Test {
    public static void main(String[] args) {
        System.out.println("1.数学计算开始前");
        //处理产生异常
        try {
            int x=Integer.parseInt(args[0]);
            int y=Integer.parseInt(args[1]);
            System.out.println("2.进行数学运算:"+x/y);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        } finally {
            System.out.println("[finally]不论是否产生异常,都执行此句");
        }
        System.out.println("3.数学计算结束后");
    }
}

当我们要处理该异常时就会发现,异常产生的原因还可边的 比如:

  • 用户没有初始化参数:ArrayIndexOutOfBoundsException (数组越界异常)

  • 用户输入的不是数字:NumberFormatException (数字格式化异常)

  • 除数为0:ArithmeticException (除零异常)

  • 当catch没有捕获到异常时,程序仍然无法进行处理,这时我们就可以使用多个catch

范例:Integer.parselnt(argsp[0]) 将String类变成int

public class Test {
    public static void main(String[] args) {
        System.out.println("1.数学计算开始前");
        //处理产生异常
        try {
            int x=Integer.parseInt(args[0]);
            int y=Integer.parseInt(args[1]);
            System.out.println("2.进行数学运算:"+x/y);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        } catch (NumberFormatException e){
            e.printStackTrace();
        } catch (ArrayIndexOutOfBoundsException e){
            e.printStackTrace();
        }
        //在多异常的情况下,给一个共同的父类Exception
        //catch (Exception e){
        //    e.printStackTrace();
        //}
        finally {
            System.out.println("[Finally]不管是否产生异常,都执行此语句" );
        }
        System.out.println("3.数学计算结束后");
    }
}
/*
1.数学计算开始前
[Finally]不管是否产生异常,都执行此语句
3.数学计算结束后
java.lang.ArrayIndexOutOfBoundsException: 0
    at www.Dyson.java.Test.main(Test.java:8)
*/

ctrl + alt + t   异常包文件

  • 无论是否产生异常,无论try catch是否有返回语句,最终都会执行finally块。处理程序退出以外的所有情况,finally都会执行如果你知道程序产生的原因并且异常较少的情况下,建议使用catch具体异常的原因,这样方法别人阅读源代码如果以后程序代码可能出现多个异常或者根本不知道会产生何种异常,可以catch共同父类Exception,而后调用printStackTrace()显示出现何种异常
  • 打印出错后异常堆栈  打印出错堆栈方法:e.printStackTrace();

throws关键字--作用于方法上

  • 在进行方法定义时。如果要明确告诉调用者本方法可能产生哪些异常,可以使用throws方法进行声明,表示将异常抛回给调用方法。并且当方法出现问题后可以不进行处理。
  • 如要调用throws声明的方法,那么在调用时必须try...catch..进行捕获,由于该方法有可能产生异常,所以必须按照异常的方式进行处理

范例:使用throws产生异常对象

public class Test {
    public static void main(String[] args) {
        System.out.println("1.数学计算开始前");
        try {
            System.out.println(calculate(10,0));
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("3.数学计算结束后");
    }
//在方法上throws异常,表示本方法可能产生异常但不处理,交由调用处处理
    public static int calculate(int x,int y) throws Exception{
        return x/y;
    }
}
/*
1.数学计算开始前
java.lang.ArithmeticException: / by zero
at www.Dyson.java.Test.calculate(Test.java:14)
at www.Dyson.java.Test.main(Test.java:7)
3.数学计算结束后
*/

throw关键字--用在方法中

  • throw语句直接写在方法之中,表示人为进行异常的抛出。
  • 如果异常对象不希望由JVM产生而通过用户产生,就可以使用throw语句来完成。
public class Test {
    public static void main(String[] args) {
        try {
            throw new Exception("自己定义的异常");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
/*
1.数学计算开始前
java.lang.Exception: 自己定义的异常
at www.Dyson.java.Test.main(Test.java:6)
*/

面试题:请解释throw和throws的区别

  • throw用于方法内部,主要表示手工异常抛出,一般与自定义异常类搭配

  • throws主要在方法声明上使用,明确告诉用户本方法可能产生的异常,同时该方法可能不处理此异

异常处理标准格式

范例:现在要求编写一个方法进行除法操作,但是对于此方法有如下要求

  1. 在进行除法计算操作之前打印一行语句"**********"

  2. 如果在除法计算过程中出现错误,则应该将异常返回给调用处

  3. 不管最终是否有异常产生,都要求打印一行计算结果信息

使用try...catch...finally

public class Test {
    public static void main(String[] args) {
        try {
            System.out.println(calculate(10,0));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static int calculate(int x,int y) throws Exception{
        int result=0;
        System.out.println("1.计算开始***********");
        try {
            result=x/y;
        } catch (Exception e) {
            //将异常抛给调用出
            throw e;
        } finally {
            System.out.println("2.计算结束-----------");
        }
        return result;
    }
}
/*
1.计算开始***********
java.lang.ArithmeticException: / by zero
2.计算结束-----------
at www.Dyson.java.Test.calculate(Test.java:14)
at www.Dyson.java.Test.main(Test.java:5)
*/

简化版:使用try...finally

public class Test {
    public static void main(String[] args) {
        try {
            System.out.println(calculate(10,0));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static int calculate(int x,int y) throws Exception{
        int result=0;
        System.out.println("1.计算开始***********");
        try {
            result=x/y;
        } finally {
            System.out.println("2.计算结束-----------");
        }
        return result;
    }
}
/*
java.lang.ArithmeticException: / by zero
1.计算开始***********
2.计算结束-----------
at www.Dyson.java.Test.calculate(Test.java:14)
at www.Dyson.java.Test.main(Test.java:5)
*/

面试题:请解释Exception与RuntimeException的区别,请列举几个常见的RuntimeException:

  • 使用Exception是RuntimeException的父类,使用Exception定义的异常都要求必须使用异常处理(受查),而使用 RuntimeException定义的异常可以由用户选择性的来进行异常处理(非受查)。

  • 常见的RuntimeException:ClassCastException(类型转化异常)、NullPointerException(空指针异常),数组越界等。

猜你喜欢

转载自blog.csdn.net/ds19980228/article/details/83689279
今日推荐