您的位置:首页 > 职场人生

黑马程序员----异常

2014-03-10 01:22 197 查看


异常:是在运行时期发生的不正常情况。

JAVA为什么会有这种机制呢?或这种情况呢?(答案在总结哪里)

比如:堵车,喝水洒电脑上了。都有可能。这些都是生活中不正常的情况。

异常时不希望发生的,但是有些是东西是避免不了的!通常都只能给出一些解决办法。


C语言对问题的处理方法,处理方法和执行语句紧密相连,阅读差和耦合性问题产生。

Java处理方法,对其问题进行封装(用面向对象的思想),把问题抛向调用者



经过对问题的封装处理,一但出现问题,直接抛出,就不需要向C语言那样去读一条条的判断语句,提高代码的阅读性!

一个很重要的解读:就是C语言它对这个问题的处理是一个面向过程的,如:买药、打水、吃药。。等,细节全部体现出来。

而JAVA基于面向对象的思想,对问题进行封装了以后,相当于一个方法。如:生病了,用药!或打针!,给出的是一个方法,具体的处理已经封装起来!

(上面不理解就不知道异常是干嘛用的!)

毕老师总结:

1,在JAVA中用类的形式对不正常的情况进行了描述和封装对象,描述不正常的类就叫----异常类。(这里我觉得说描述并封装对象更好)

(其实就是细节隐藏起来,给你个方法)。

,2,以前正常流程代码和处理代码相结合,现在将正常流程代码和问题处理代码分离,提高阅读性。(就是把问题细节封装了,给个方法!)

总结:其实异常就是JAVA通过面向对象的思想将问题封装成了对象,用异常类来描述。

封装的方式:用类进行具体的描述,如角标越界、空指针(这些很多都是JAVA封装好了的。)

以上是异常的概述


问题出现了,怎么告诉调用者啊?return?那不就以为着函数带返回值?抛吧!

Throwable:无论是error,还是异常,问题,问题发生就应该可以抛出,让调用者知道并处理。

//该体系的特点就在于Throwable及其所有的子类都具有可抛性。

可抛性到底指的是什么呢?怎么体现可抛性呢?

其实是通过两个关键字来体现的。

throws throw ,凡是可以被这两个关键字所操作的类和对象都具备可抛性.

|--1,一般不可处理的。Error

特点:是由jvm抛出的严重性的问题。

这种问题发生一般不针对性处理。直接修改程序

|--2,可以处理的。Exception

该体系的特点:

子类的后缀名都是用其父类名作为后缀,阅读性很想。

以上是异常体系



异常说明很清楚,解读:Demo这个类中的method方法出现异常,在第7行出的问题,很清楚

ExceptionDemo2这个类中main方法出现异常,在第18行出的问题,都很清楚!



JVM对这个问题是什么处理的?在越界的地方new一个对象出来,然后main函数调用了这个对象,所以抛给了main函数,而main函数也没有处理,就抛给JVM,JVM 也就抛给我们程序员!然后我们就可以处理嘛!(补充一点,真实开发中出现的异常问题,就是JVM抛出来的,作为日志保存起来,有用!)



毕老师怕学生不理解:特意加了两条语句,问能不能执行到,明显是不能的,因为遇到异常的时候就抛出去了,最后JVM也抛给了程序员!

顺便说到异常抛出是JVM帮忙抛的,那我们自己能不能抛呢?明显是可以自己抛的,那自己抛的目的是什么呢?(初步原因是JVM抛出来的感觉不爽!)


这个类的构造函数有,我们可以自己new一个爽的异常详细信息!



原来是想return返回处理这个问题的结果,但是毕老师说很难处理(暂时不是很理解!可以先试试对象的处理方法)



throw new ArrayIndexOutOfBoundsException() ; 的时候后面没带信息”3“,不详细

throw new ArrayIndexOutOfBoundsException(index); 的时候,Array index out of range :3 又多出几个单词来。。。不想要?下面继续

throw new ArrayIndexOutOfBoundsException(" "+index) ;这样就行了,自己定义一个空格,不知道JVM抛出来的是不是也是这样。。。(其实跟下面那句一样!)

throw new ArrayIndexOutOfBoundsException(" 数组角标越界了,哥们,你疯了?"+index); 自己定义的异常信息。 (这里就可以说明自己抛的可以更详细)



这里说到空指针异常的时候,查看API文档NullPointerException的构造函数,发现都可以传入自己定义的信息,都可以带(String s),字符串嘛,自己定义清晰明了!

小节:这节说明了一下JVM是怎么抛出的,然后我们怎么样也可以自己抛出详细的异常信息!

以上是异常原理&异常对象的抛出throw



说到AarryIndexOutOfBoundsException这个信息来说明角标不能为负数有点不太贴切------------进而引出自定义异常了!(毕老师讲课的牛B处了,逻辑强啊!)



定义异常类须知:要成为异常类,需要继承异常体系,只有异常体系才能被 throw throws操作!



这个用来说一下JAVA是先检查语法错误,然后再检查异常或其它的。


打开API的一个函数说明这些方法都是只能看到方法说明(其实就想说在函数上声明异常!)



话说这个异常要抛需要在函数上声明,然后让调用者知道,最终的调用者就是JVM嘛,这些都能理解。

问题:自定义的异常类都是要自己抛?而JAVA定义的异常类就JVM抛?这就是自定义异常类和JAVA定义异常类的区别?(前提不处理就抛而言说明这个问题)



这里我还以为要覆盖父类的方法,忘了继承后可以直接使用父类的方法了!傻了!好吧!!

这节课后面毕老师直接说到我的问题了:自定义异常类和JAVA定义的异常类区别在哪里呢?接下来下节课应该就知道答案了!O(∩_∩)O~~~!

以上是自定义异常&异常类的抛出throws

上节课答案揭晓:原来例子里面的两个异常类的父类都是RuntimeException,所以,自定义的异常类继承了RuntimeException后,编译就能通过了。

异常的分类:

1,编译时被检测异常:只要是Exception和其子类都是,除了特殊子类RuntimeException体系。

2,编译时不检测异常(运行时异常):就是 Exception中的RuntimeException 和其子类。

话说:为什么会有这样的分类呢?

答案:编译时被检测异常:这类问题一旦出现,希望在编译的时候就进行检测,让这种问题有对应的处理方式,而且这样的问题都可以针对性处理。

编译时检测异常:这种问题的发生,无法让功能继续,运算无法进行,更多是因为调用者的原因导致的而引起发生了内部状态的改变导致的。

那么对于这种问题一般不做处理,直接编译通过,在运行时,让调用者调用时的程序强制停止,让调用者对代码进行修正。



以上是异常-编译时检测异常和运行时异常的区别&throw和throws的区别


基本格式。

try里面放的是需要被检测异常的代码。

异常类变量,该变量是用于接受发生异常的对象

catch里面放的是处理异常的代码。

finally是一定要执行的代码。

安检例子:try就是检测(相当于安检机),catch是抓取(发现手雷后就抓取,然后接着处理)。没catch就没处理。

什么时候抛,什么时候处理?

如果你能处理,就处理,不能就抛。


对问题的捕捉处理,处理完后会继续运行!



话说:这个就是接受处理的一个图,那么,catch接受到了对象以后,怎么就没有使用这个对象呢?



那么就使用吧!继承了异常体系,Throwable里面的方法都可以调用。



一般的对象打印字符串都是类型地址哈希值,而异常对象有特定的打印方式。隐藏e.toString()



其实JVM默认的异常处理机制就是调用异常对象的printStackTrace();

log4j,做日志用!!

多catch情况:


面试用的:父类异常处理要放在子类异常处理后面,不然就处理不到。(否则就编译失败)

(正常情况下都是抛几个就处理几个,没有人这样写的,面试用!)



这里引出了一个预先try(预先处理的问题),那么catch 的时候就(Exception e)作为对象,那么就怎么异常都可以接受,就会隐藏掉问题。所以一般都是发生了问题再处理。让问题暴露出来!



说到这catch里面别什么都不写,要用于日志的。



说明一下finally的一个效果!


是不是finally肯定会执行?答案:不是,退出JVM就执行不到了!

这finally什么时候用呢?数据库例子:访问完后要断开,不然浪费资源啊!(所以是用来释放资源用的!)


没处理,就抛!有catch,才有处理

try catch finally代码块组合特点:

1,try catch finally

2,try catch(可以多个),当没有必要关闭资源的时候,可以不定义finally

3,try finally 异常无法直接catch处理的时候,但是开启资源后需要关闭。

异常应用的一个练习:

/*
毕老师用电脑上课。

问题领域中涉及两个对象。
毕老师,电脑。

分析其中的问题。

比如电脑蓝屏啦。冒烟啦。

*/
/********************异常类自定义*********************/

class LanPingException extends Exception //继承Exception,因为我能处理
{
LanPingException(String msg)//父类中有这个方法,直接拿过来用
{
super(msg); //super(String msg)有写错成这样,说明不熟练
}
}

class MaoYanException extends Exception
{
MaoYanException(String msg)
{
super(msg);
}
}
class NoPlanException extends Exception
{
NoPlanException(String msg)
{
super(msg);
}
}
/***********************电脑对象描述**************************/

class Computer
{
private int state = 1;
public void run()throws MaoYanException,LanPingException
{
if(state==1)
throw new MaoYanException("电脑冒烟了!!");
if(state==2)
throw new LanPingException("电脑蓝屏了!!");

System.out.println("电脑正常运行");
}
public void reset()
{
state = 0;    //这里练习的时候忘了加上,导致perlect()无限调用。
System.out.println("电脑重启了");
}
}

class Teacher
{
private String name;
private Computer comp;   //定义一个类类型变量
Teacher(String name)
{
this.name = name;
comp = new Computer();//为什么不直接定义Computer comp = new Computer();
}                          //因为这样定义的话comp就变成了局部变量了
//构造函数初始化完后comp就消失了,后面怎么调用?
public void prelect()throws NoPlanException
{
try
{
comp.run();
System.out.println(name+"讲课");

}
catch (LanPingException e)
{
System.out.println(e.toString());//返回此 throwable 的简短描述。
comp.reset();
prelect();
}
catch (MaoYanException e)
{
System.out.println(e.toString());
test();
//问题还没有解决,就继续抛
throw new NoPlanException("告诉学校电脑坏了...."+e.getMessage());
//getMessage()   返回此 throwable 的详细消息字符串

}
}
public void test()
{
System.out.println("大家练习");
}

}
class ExceptionTest
{
public static void main(String[] args)
{
Teacher t = new Teacher("毕老师");
try
{
t.prelect();

}
catch (NoPlanException e)
{
System.out.println("e.getMessage():"+e.getMessage()+"......");
System.out.println("e.toString():"+e.toString()+"......");

//以上是用于区别一下e.getMessage()和e.toString()
System.out.println("换人");

}

}
}


异常的注意事项:

1,子类在覆盖父类方法时,父类的方法如果抛出了异常,

那么子类的方法只能抛出父类的异常或者该异常的子类。

2,如果父类抛出多个异常,那么子类只能抛出父类异常的子集。

简单说:子类覆盖父类只能抛出父类的异常或者子类或者子集。

注意:如果父类的方法没有抛出异常,那么子类覆盖时绝对不能抛,就只能try .(有异常的时候不用抛只能try)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: