1. 异常:异常是导致程序中断运行的一种指令流,如果不对异常进行正确的处理,则可能导致程序的中断执行,造成不必要的损失,所以在程序的设计中必须要考虑各种异常的发生,并做好相应的处理,这样才能保证程序正常执行。
2. 为什么产生异常?
因为我们写的程序中,可能会出现一些,意料不到的结果,所以这时候我们用到异常的话,那怕程序出现状况,异常就会自动抛出或者解决。
比如:两个数相除,其中被除数为0的话,计算机内存会被占满,因为零分之一为无穷大,任何数乘以零分之一都为无穷大 ,则就会出错:
举例:
public class Exception {
public static void main(String[] args) {
System.out.println("======计算开始======");
int i = 10;
int j = 0;
int temp = i/j;//此处产生异常
System.out.println("两个数相除的结果是:" + temp);
System.out.println("=======计算结束=======");
}
}
运行结果:
======计算开始======
Exception in thread "main" java.lang.ArithmeticException: / by zero
at ZhangRun.club.Exception.main(Exception.java:8)
由以上代码知道,只要程序产生异常,异常之后的语句并不会执行,而是直接结束程序,并把错误报告给用户。
3. 异常处理格式:
try{
//有可能出现异常的语句
}catch(异常类 异常对象){
//编写异常的处理语句
}。。。。
finally{
一定会运行到的程序代码;
}
举例:
public class Exception2 {
public static void main(String[] args) {
System.out.println("======计算开始======");
int i = 10;
int j = 0;
try{
int temp = i/j;
System.out.println("两个数相除的结果是:" + temp);
System.out.println("=========================");
}catch(Exception e){
System.out.println("出现异常了:" + e);
}
System.out.println("=======计算结束=======");
}
}
运行结果:
======计算开始======
出现异常了:java.lang.ArithmeticException: / by zero
=======计算结束=======
以上操作代码中只使用了基本的异常处理格式:try.....catch.try 中捕获异常,出现异常之后的代码将不再被执行,而是跳转到相应的catch语句中执行,用于处理异常。
当然,对于异常也可以设置其统一的出口,使用finally 完成。
举例:
public class Exception2 {
public static void main(String[] args) {
System.out.println("======计算开始======");
int i = 10;
int j = 0;
try{
System.out.println("=======");
int temp = i/j;
System.out.println("两个数相除的结果是:" + temp);
System.out.println("=========================");
}catch(Exception e){
System.out.println("出现异常了:" + e);
}finally{//作为异常统一出口
System.out.println("不管是否出现异常,都执行此代码!");
}
System.out.println("=======计算结束=======");
}
}
运行结果:
======计算开始======
=======
出现异常了:java.lang.ArithmeticException: / by zero
不管是否出现异常,都执行此代码!
=======计算结束=======
4. 异常类的继承结构
在整个java 的异常结构中,实际上有以下两个最常用的类:Exception,Error,这两个类全都是Throwable的子类
Exception:一般表示的是程序中出现的问题,可以直接使用try......catch处理。
Error:一般指的是JVM错误,程序中无法处理。
一般情况下开发者都习惯将Exception,Erro统一称为异常,而之前处理的若干异常,全部都是Exception的子类。
注意:一般在输出异常信息的时候,可以直接使用System.out.println();打印异常对象。
也可以通过Exception提供的一个方法:public void printStackTrace();
举例:
public class Exception2 {
public static void main(String[] args) {
System.out.println("======计算开始======");
int i = 10;
int j = 0;
try{
System.out.println("=======");
int temp = i/j;
System.out.println("两个数相除的结果是:" + temp);
System.out.println("=========================");
}catch(Exception e){
//System.out.println("出现异常了:" + e);
e.printStackTrace();//打印出异常信息和异常出现的行数
}finally{//作为异常统一出口
System.out.println("不管是否出现异常,都执行此代码!");
}
System.out.println("=======计算结束=======");
}
}
运行结果:
======计算开始======
=======
java.lang.ArithmeticException: / by zero
不管是否出现异常,都执行此代码!
=======计算结束=======
at ZhangRun.club.Exception2.main(Exception2.java:10)
5. java异常处理机制
在整个Java的异常处理中,实际上也是按照面向对象的方式进行处理的,处理步骤如下:
(1) 一旦产生异常,则首先会产生一个异常类的实例化对象;
(2)在try 语句中对此异常对象进行捕捉;
(3)产生的异常对象与catch语句中的各个异常类型进行匹配,如果匹配成功,则执行catch语句中的代码。
前几篇文章中说过对象的多态性:子类的实例化对象可以直接使用父类的对象(向上转型)进行接收。
那么在异常处理中,实际上也是使用此种概念,,因为try中产生的是一个实例化对象。如果现在有一些其他的异常无法知道的话,可以用Exception进行捕获。
注意点:在异常处理中,捕获更粗的异常要放在捕获更细的异常之后 。如
ArithmeticException就比Exception异常捕获细。
ArithmeticException如果放在Exception后面就会报错,因为执行到Exception时异常就被捕获了,提示算术异常,这时候后面的ArithmeticException异常就不会在次被捕获了。
总结:捕获异常时可以直接使用Exception 进行捕获,当然,在一个比较细致的开发中是不建议这样使用的,所有的一次最好分别捕获。
6.问题
既然捕获Exception是最方便的,那么直接捕获Throwable可不可以?
Exception是Throwable子类,首先这样的做法是可以的,但是正常的开发人员不会这样做,因为在程序的try 中永远只会抛出Exception的子类,而Throwable中不光有Exception还有Error。
7.总结
(1)异常出现之后,如果没有合理处理的话,则会让整个程序执行中断。
(2) 使用try ... catch 和 try ...catch....finally 可以处理异常,finally将作为异常的统一出口,不管是否有异常都回执行此语句。
(3)一个异常处理中可以同时出现多个catch,但是捕获更粗的异常要放在捕获更细的异常之后,否则程序编译时将会出错。
(4)在异常中最大的类是Throwable ,分为两个子类:Exception,Error。
Exception :是程序可以自己处理的异常;
Error :表示JVM错误,一般程序无法处理
(5)捕获的时候可以直接捕获Exception,但是最好分开捕获,如果所有的异常处理操作是一样的话,则也可以直接捕获Exception。
(6)每当异常产生之后,会在程序中产生一个异常类的实例化对象,之后使用此对象与catch中的异常类型相匹配,如果匹配成功,则执行catch语句中的内容,如果匹配不成功,则向下继续匹配,如果都无法成功,程序出现中断问题。