异常:
是在运行时期发生的不正常情况
Java发现不正常的情况都包含着一些常见信息,并 将这些信息进行了对象的封装。
异常这种机制,其实就是java按照面向对象的思想将出现的问题封装成了对象。
在进行问题分析时,发现问题有很多种,但是不断向上抽取,最终问题可以归纳为两种,一种是可以针对处理的一种是通常不进行处理的。
在java中的体现一个是Exception ,一个是Error,后者一般针对处理。
无论是异常还是错误,他们都有名称信息等共性的内容。
可以继续抽取形成一个父类:throwable可抛出。
Throwable
|---Error
|---Exception
异常和错误都有一个特点:其子类的名称的后缀名都是父类名。
该体系具备一个特殊的特性叫做可抛性,该体系中的类可以被关键字throws抛出。
该体系中的类产生的对象可以被Throw抛出,简单说该体系可以被Throws 和throw操作。
Throw 和throws的区别:
Throws:定义在函数上,用于声明函数的可能出现的问题,后面跟异常类,可以跟多个,用逗号隔开、
Throw:定义在函数内,用于抛出异常对象因为程序的跳转,后面跟的是异常对象。
try
{
需要被检测的代码;
}
catch(异常类 变量)
{
处理异常的代码(处理方式)
}
finally
{
一定会执行的语句:
}
异常处理 代码详解:
class DemoDiv
{
int div(int x,int y)
{
//【2】进行运算,一除就引发了问题(java虚拟机的算数问题
return x/y;//把AritchmeticException()问题封装成了对象,并把这个问题抛给了调用这个问题的调用者,主函数 div(6,0)上
}
}
class ExceptionDemo
{
//注:当没有检测到问题时,主函数没办法处理问题,给虚拟机处理,虚拟机采用默认处理,调用了默认的异常处理机制
public static void main(String[] args)
{
//【1】首先在主函数在内存中建立了对象,当d对象调用了div函数把值传给了div x,y
Demo d = new Demo();//
try //【3】try尝试检测问题并检测到了,并把AritchmeticException()问题丢给了catch
{
int x = d.div(6,0);
System.out.println("x="+x);//未执行
}
catch (Exception e)//【4】catch Exception e是Exception类型的引用变量
// => Exception e = new ArithmeticException();
{
System.out.println("除零了!");//【5】最后执行了处理代码,代表者问题被处理,没问题运行了
}
System.out.println("结束!");//【6】打印结束!
}
}
异常分两种:
1、编译被检测的异常:Exception
这种异常通常都需要进行针对性的处理。
2、运行时发生的异常:RuntimeException
对于运行时异常一般是不编写针对性的处理方式,如果该异常发生就让程序停止,
对程序进行修正。因为这种的出现往往已经无法让程序继续运算了。
class Demo
{
//在功能上通过throws的关键字声明了该功能有可能出现问题
int div(int a,int b)throws ArithmeticException
{
if(b==0)
throw new ArithmeticException("除数为零");
return a/b;
}
}
class ExceptionDemo3
{
public static void main(String[] args)
{
getIndex(null,4);
}
public static int getIndex(int[] arr,int key)
{
if(arr==null)//进行健壮性判断。
throw new NullPointerException("没有具体的数组");
for(int x=0;x<arr.length;x++)
{
if(arr[x]==key)
return x;
}
return -1;
}
public static int getElement(int[] arr,int index)
{
if(arr==null)
throw new NullPointerException("没有具体的数组实例");
if(index<0||index>=arr.length)
throw new ArrayIndexOutOfBoundsException("角标越界");
return arr[index];
}
}
总结:
1、定义功能时,功能中有什么问题,都应该进行预先的处理比如try catch.如果处理不了,应该通过throws声明抛出,让调用者进行处理。
2、调用了抛出异常的功能的函数,应该进行处理,如果使用try catch处理的话,被调用的功能上抛出几个异常,就应该对应几个catch语句,必须要对多个异常进行针对性的处理。
3、如果出现多个catch中存在着父类异常的catch,那么这个catch一定放在catch的最后,通常这种情况在面试很多见。
4、如果函数内抛出异常,那么一定要在函数上声明,否则编译失败,但是要注意函数内抛出的异常是运行时异常(RuntimeException),那么函数上是可以不用throws声明的。
5、如果函数内抛出了异常,进行了本功能内部的处理,但是处理的并不完全,这时应该在异常处理中,继续将异常抛出,让在函数上声明让调用者知道问题的存在,但是有可能需要将异常进行转换,尽量抛出调用者识别的异常,处理起来更方便。
6、当子类覆盖父类中的异常声明的方法时,子类方法只能声明父类的异常或者该异常的子类。如果父类抛出了多个异常,那么子类在覆盖时买智能抛出父类异常的子集。
7、如果父类和接口中的方法没有声明抛出过异常,那么子类的覆盖父类方法时,也不能抛出异常,如果子类中的方法发生了异常,那么子类只能try catch不能用throws声明,只能try,不能抛,如果非要在函数内抛出异常,那么只能抛出RuntimeException,因为这种异常不用在函数声明上。
2、finally:
定义一定会被执行的代码。通常用来关闭资源,
异常处理的三种格式:
1、try catch finally
2、Try catch//可以多个catch
3、Try finally
记住:catch是用于处理异常的,如果没有catch就代表异常没有被处理过,如故哦该异常是检测时异常,必须被声明。
3、异常总结:
异常是什么?是对问题的描述,将问题进行对象的封装。
异常体系:
Throwable
|---Error
|--Exception
|--RuntimeException
异常体系的特点:
异常体系中的所有类以及建立的对象都具有可抛性。
也就说可以被throw和throws关键字操作。
只有异常体系具备这个特点。
Throw和throws的用法:
Throw定义在函数内,用于抛出异常对象。
Throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。
函数内有throw抛出异常对象,并未进行try处理必须要在函数上声明,否则编译失败, 注意:RuntimeException异常除外,也就说函数内如果抛出的是RuntimeException
函数上可以不用声明,如果函数声明了异常,调用者需要进行处理 吗,
处理方式throws也可以try
异常有两种:
1、编译时检测异常:
该异常在编译时如果没有处理,如果没有处理(没有抛也没有try)编译失败
2、运行时异常
在编译时,不需要处理,编译器不检查,该异常发生,建议不处理,让程序停止,需要对代码进行修正。
异常处理的语句:
try
{
需要被检测的代码
}
catch()
{异常处理代码}
fianlly
{一定会执行的代码}
有三种结合的格式:
1、try{}catch(){}finally{}
2、try{}catch(){}
3、try{}finally{}
注意:
1、finally中定义的通常是关闭资源,因为资源必须被释放。
2、finally只有一种情况不会执行,当执行到System.exit(0);finally
不会执行。
5、自定义异常
定义类继承Exception或者RuntimeException
1、为了让该自定义类具备可抛性。
2、让该类具备操作异常的共性方法。
当要定义自定义异常的信息时,可以使用父类已经定义好的功能
将异常信息传递给父类的构造函数,
自定义异常:按照java的面向对象思想,将程序中出现的特有问题进行封装。
异常的好处:
1、将问题进行封装。
2、将正常流程代码和问题处理代码相分离,方便阅读
异常的处理原则:
1、处理方式有两种:try 或者throws。
2、调用到抛出异常的功能时,抛出几个就处理几个。
一个try对应多个catch的情况。
3、多个catch父类的catch放到最下面。
4、catch内需要定义针对性的处理方式,不要简单的定义printStackTrace,输出语句。
也不要不写。当捕获到的异常,本功能处理不了时,可以继续在catch中抛出。
try
{
throw new AException
}
catch(AException e)
{
throw e;
}
如果该异常处理不了,但并不属于该功能出现的异常,可以将异常转换后,在抛出和该功能相关的异常。
或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去,当调用者知道,并处理,也可以将捕获的异常处理后,转换新的异常。
try
{
throw new AException();
}
catch(AException e)
{
throw new BException();
}
比如汇款的列子:
异常的注意事项:
在子父类覆盖时:
1、子类抛出的异常必须是父类异常的子类或者子集。
2、如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能抛。
/*
证明return是在finally执行后才返回的,且在finally无法改变返回值。
*/
class FinallyTest
{
public static int demo()
{
int a = 1;
try
{
System.out.println("try的 a:"+a);
return a;//需要被检测的代码块
}
finally //一定会执行的语句
{
a=5;
System.out.println("finally的 a:"+a);
//return 15;
}
}
public static void main(String[] args)
{
System.out.println("demo:"+demo());//调用demo,如果打印结果为1证明 finally不能改变try里面的返回值
}
}
![](https://img-my.csdn.net/uploads/201209/05/1346827180_5431.png)