-------android培训、java培训期待与您交流!----------
java用面向对象的思想将现实中的问题封装成相应的类,并进行处理。形成了java的异常处理机制。
编写程序中异常是不可不避免,非常常见的。
如打开一个不存在的文件,URL地址不存在,等等。不妥善的处理这些异常,往往会使程序逻辑混乱,用户体验糟糕之极。
在java中将问题分为两种。
严重的:用Error类及其子类描述。对于它不编 写针对性代码。
非严重的:用Exception类及其子类描述。可以编写代码进行针对性的处理。
异常的分类:
异常分为 编译时异常和运行时异常。
编译时异常:必须要在函数上声明或者捕获处理(try-catch)。
运行时异常:即RuntimeException 或其子类。它是Exception体系中比较特殊的一种异常。可以不用声明,调用者可以不进行处理,一旦错误使用该方法程序就会停止。
之所以这样是因为RuntimeException通常是因为调用者错误的使用函数所引起的,这对于函数的实现者来说该异常是他所不能处理的,为了让调用者正确使用函数,可以在函数里抛出异常,而在函数上不声明,以免调用者将异常隐藏。这样调用者如果错误的使用了该方法程序就会停止并报错,直到他修正好代码方能继续运行程序。
常见的运行时异常有数组角标越界异常(ArrayIndexOutOfBoundsException)java最常见也最恶心的空指针异常(NullpostException)。
异常的处理语句:
try{
被检测有可能出现异常的代码
}catch(异常类 变量名){
处理异常的代码
}finally{
一定会执行到的代码
}
try语句块里放置需要检测,可能会出现的异常的代码。当虚拟机在try语句块里捕获到异常时,会将异常封装成对象传给catch语句块。在catch语句块中给予处理该异常的代码。finally语句块中是一定会执行的代码。通常会放置一些与资源有关操作的代码。如关闭IO流,断开与数据库的连接。这里有一点要注意,有一种情况finally语句块里的代码会执行不到。当虚拟机在要执行它之前执行了System.exit(0)方法后,会退出系统,finally里的语句不会执行。
异常处理语句的格式:
1.try{
}catch(){
}
2.try{
}finally{
}
3.try{
}catch(){
}finally{
}
异常的处理方法 捕获处理或声明。
捕获处理:用try-catch -finally语句进行捕 获处理。
声明:当函数中可能会抛出异常时,可以不用try语句块捕获处理,可以在函数上用关键字throws new异常类名()的方式声明异常。
异常处理的原则:
1.处理方式只有两种。要么抛(throws)在函数上声明。要么try(捕获处理).
2.调用声明了异常的方法时,方法上声明了几个异常,就用几个catch语句块进行处理。
3.多个catch时父类的异常要放在最下面。如果不这样编译会不能通过。
4.当在catch语句块中处理异常时,可以根据实际需求,如想给调用者反馈一些有关于它的信息,可以就续抛出异常。
5.这是对第四点更细致的讲解。当捕获的异常可以处理,但需要将异常产生的和基本功能相关的问题提供出去.可以将捕获的异常处理后转换成新的调用者能处理的异常抛出去。
自定义异常:java中定义了很多的异常。但在我门实际开发时经常有些我们自己认为是问题的东西。我们同样可以用面向对象的思想,将这些问题封装成类,自定义异常。只要该类继承了Exception类,就能成为java中异常体系中的一员。就具有了可抛性。我们还可以利用异常类的构造器,将更为详细的异常信息放置在自定义的异常类中。自定异常通常可以这样写:
public class MyException extends Exception{
MyException(String message){
super(message)//调用父类构造函数进行初始化。
}
}
自定义类名通常与Java中的异常类名一样,以Exception为后缀名。利用父类的构造函数我们在new 自定义异常对象时可以传入更丰富的异常信息描述。
手动抛出异常:说道自定义异常就必须要说手 动抛出异常的操作了。手动抛出异常用关键字throw 异常对象 这种形式的代码实现。
java 虚拟机只认识java已经定义好的异常,一旦它发现那些java定义好的异常发生了就会自动将该异常对象抛出。但是自定义异常时,java虚拟机并不认识该异常,需要程序员手动抛出该异常。
当然 throw并不只是可以抛出自定义异常,它可以抛出任何异常。程序员可以根据需要用throw主动抛出任何异常。
throw 与throws的区别:
用法上:throws是用来给函数声明该函数有可能出现的异常。而throw 是用来在函数中手动抛出异常对象的。
出现的位置:throws 是写在函数上 函数名后面的小括号和大括号之间,而throw则是写在函数里即大括号里的。
子父类方法覆盖时的异常:
当子类覆盖了父类的方法。他的方法(覆盖了父类方法的方法)所能抛出的异常在 数目上说:子类抛出的异常数目必须小于或等于父类抛出的异常数目。父类没有抛出异常的话,子类也不能抛出异常。
种类上说:子类只能抛出与父类一样或是父类抛出的异常的子类的异常。
原因时,以前对父类异常处理的代码无法处理子类新增的异常。如果子类真的有可能出现违反规则的异常,就只能try不能声明。
说了这么多,我觉得对java异常的学习最重要的是灵活的运用,根据自己的程序需求,定义自定义异常类,对异常的处理和传递。
下面的代码是描述毕老师用电脑上课,并对其中的异常进行处理。综合一下上面的知识。
package ErrorAndException;
/**
* 本例描述的是毕老师上课,并处理其中可 能出现的异常。
关键是掌握自定义异常,对异常的转换与传递
*
*
*/
public class Price1 {
static int state=2;//该变量用于模拟异常发生,1为蓝屏2为冒烟
public static void main(String[] args) throws NoPlaneException{
// TODO Auto-generated method stub
Coupter cou=new Coupter();
Teacher te=new Teacher("毕老师",cou);
try{
if(state==1)
throw new LanPingException("蓝屏了呜呜");
if(state==2)
throw new MaoYanException("冒烟了");
te.jianKe();
}
catch(LanPingException lan){
te.getCou().chongQi();//重启电脑
te.jianKe();
state=0;
}
catch(MaoYanException my){
/**重点在这里,毕老师的电脑冒烟了,它处理的办法是不上课了,让学生做练习。
* 但比老是的调用者,校长(这里假设main函数就是校长)。调用毕老师讲课,是为了让教学计划正常执行。这时毕老就应该向校长报告一个他能处理的异常。但如果是报告MaoYanException决对不合适,校长不能处理电脑冒烟的异常。这时就需要灵活转换异常抛。NoPlaneExceotion抛给调用者。调用者得到需要的信息并可以根据getCause()得到异常发生的原因使异常链不断掉
*/
te.BuZhiLianXi();
throw new NoPlaneException("教学进度赶不上了",my);
}
System.out.println("程序over");
}
}
//自定义异常描述电脑蓝屏的异常
class LanPingException extends Exception{
LanPingException(String s){
super(s);
}
}
//自定义异常描述电脑冒烟的异常
class MaoYanException extends Exception{
MaoYanException(String s,MaoYanException e){
super(s,e);
}
}
//自定义异常类 描述授课计划赶不上的异常,该类可以接受引起它发生的异常对象。
class NoPlaneException extends Exception{
NoPlaneException(String s,){
super(s);
}
}
//老师类
class Teacher{
private String name;
private Coupter cou;
public Coupter getCou() {
return cou;
}
public void setCou(Coupter cou) {
this.cou = cou;
}
Teacher(String name,Coupter cou){
this.name=name;
this.cou=cou;
}
//讲课方法
void jianKe(){
cou.run();
System.out.println("毕老师在讲课");
}
void BuZhiLianXi(){
System.out.println("布置练习题给学生做");
}
}
//电脑类
class Coupter{
//电脑运行的方法
void run(){
System.out.println("电脑运行");
}
//电脑重启的方法
void chongQi(){
System.out.println("电脑重启");
}
}