异 常
1、概述
*是在运行时期发生的不正常情况。
*在java中用类的形式对不正常情况进行了描述和封装
*描述不正常的情况的类,就称为异常类
以前正常流程代码和问题处理代码相结合
现在将正常流程代码和问题处理代码分离,提高阅读性
其实异常就是java通过面向对象的思想将问题封装成了对象。
2、异常体系
(1)用异常类对其进行描述
不同的问题用不同的类进行具体的描述,比如脚标越界,空指针等等
问题很多,意味着描述的类也很多
将其共性进行向上抽取,形成了异常体系
(2)异常的体系(Throwable):
*Error //错误,一般不可处理的。
**通常出现重大问题如:运行的类不存在或者内存溢出等。
**不编写针对代码对其处理
特点:是由jvm抛出的严重性的问题。
这种问题发生,一般不针对性处理,直接修改程序
*Exception //例外,可以处理的
**在运行时运行出现的一些情况,可以通过try,catch,finally进行捕获处理
(3)Throwable:无论是error,还是异常,都是问题,问题发生就应该可以抛出,让调用者知道并处理。
该体系的特点就在于Throwable及其所有的子类都具有可抛性。
(4)可抛性到底指的是什么?怎样体系有可抛性呢?
其实是通过两个关键字来体现的。
throws和throw,凡是可以被这两个关键字所操作的类和对象都具备可抛性。
(5)该体系的特点:
子类的后缀名都是用其父类名作为后缀,阅读性很强。
Exception和Error的子类名都是以父类名作后缀
对于脚标是整数不存在,可以用脚标越界表示
对于负数为脚标的情况,准备用负数脚标异常来表示
负数脚标这种异常在java中并没有定义过,对于java 中没定义过的异常,那就按照java异常的创建思想,面向对象,将负数脚标进行自定义描述。并封装成对象。这种自定义的问题描述称为自定义异常。
注意:如果让一个类称为异常类,必须要继承异常体系,因为只有称为异常体系的子类才有资格具有可抛性。才可以被两个关键字所操作。
(6)异常的分类:
*编译时被检测异常:只要是Exception和其子类都是,除了特殊子类RuntimeException体系。
这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式。这样的问题都可以针对性的处理。
*编译时不检测异常(运行时异常):就是Exception中的RuntimeException和其子类。
这种问题的发生,无法让功能继续,运算无法进行,更多是因为调用者的原因导致的或者引发了内部状态的改变导致的。
那么这种问题一般不处理,直接编译通过,在运行时,让调用者调用时的程序强制停止,让调用者对代码进行修正。所以自定义异常时,要么继承Exception。要么继承RuntimeException。
(7)throws和throw
*throws用于标识函数暴露出的异常
*throw用于抛出异常对象。
定义功能方法时,需要把出现的问题暴露出来让调用者去处理。那么就通过throws在函数上标识。
在功能方法内部出现某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出。
*throws与throw的区别:
**throws用在函数上,后面跟着异常类名
**throw用在函数内,后面跟异常对象
(8)异常处理的捕捉形式:
这是可以对异常进行针对性处理的方式
具体格式:
try{
//需要被检测异常的代码
}catch(异常类 变量){//该变量用于接收发生的异常对象。
//处理异常的代码
}finally{
//一定会被执行的代码。
}
Catch用于处理异常,没catch则没有处理
(9)Throwable(异常)中的方法:
*getMessage()
获取异常信息,返回字符串。
*toString()
获取异常类名和异常信息,返回字符串。
*printStackTrace()
获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void
*printStackTrace(PrintStream s)
通常用该方法将异常内容保存在日志文件中,以便查阅。
(10)异常处理的原则:
*函数内部如果抛出需要检测的异常,那么函数上必须要声明,要么必须在函数内用try catch捕捉,否则编译会失败
*如果调用到了声明异常的函数,要么try catch要么throws,否则编译失败;
*什么时候catch,什么时候throws呢?
功能内部可以解决用catch。
解决不了,用throws告诉调用者,由调用者解决;
*一个功能如果抛出了多个异常,那么调用时,必须有对应多个catch进行针对性的处理。
内部有几个需要检测的异常,就抛几个异常,抛出几个,就catch几个。
(11)异常处理过程:
*Try中检测到异常会将异常对象传递给catch,catch捕获到异常进行处理;
*Finally里通常用来关闭资源。比如:数据库资源,IO资源等。
需要注意:try是一个独立的代码块,在其中定义的变量只在该代码块中有效。
如果在try以外继续使用,需要在try建立引用。在try对其进行初始化,IO,Socket就会遇到。
try{
需要检测的代码;
}catch(异常类 变量){
异常处理代码;
}finally{
一定会执行的代码;
}
Finally代码块只有一种情况不会被执行。就是在之前执行了System exit(0)
(12)try catch finally代码块组合特点:
1、try catch finally组合
2、try catch(多个)当没有必要资源需要释放时,可以不用定义fianlly
3、try fianlly异常无法直接catch处理,但是资源需要关闭。
(13)异常的注意事项:
*子类在覆盖父类方法时,父类的方法如果抛出了异常,那么子类的方法只能抛出父类的异常或者该异常的子类
*如果父类抛出多个异常,那么子类只能抛出父类异常的子集。
简单说:子类覆盖父类,只能抛出父类的异常或者子类或者子集
注意:如果父类的方法没有抛出异常,那么子类覆盖时绝对不能抛,就只能try。
当父类中没有标示时,子类只能try不能抛,只能内部解决。
包(package)
1、概述
对类文件进行分类管理
可以给类提供多层命名空间
写在程序文件的第一行
类名的全称是:包名.类名
包也是一种封装形式
2、命名空间(名称空间):存储该文件的空间,即存储在哪个地方,哪个地方就是其存在的命名空间。
带有包的源文件生成的字节码文件,执行时需要加前缀包名
编译时需加-d才能生成存放类文件的位置,即生成以源文件中包名命名的文件夹存放类文件
当需要在当前目录下生成文件夹或文件时,可用“ . ”表示
例:javac -d . Demob.java则生成的Demob.class文件会存放在当前目录下新建的该源文件中以包名命名的文件夹里
可以生成多层包目录:即源文件中将包名写成多级的,如:原包名:package packb;改成package packb.haha.hehe.xixi,则
会创建四层文件夹
3、classpath
*给JVM提供的一个环境变量
*指定类或者包所在的路径
*classpath变量值的最后有分号与无分号的区别。
**有分号时,JVM会先到classpath指定的目录下寻找类文件,如果没有找到会在当前目录下寻找;
**没有分号,JVM会先到classpath指定目录寻找,没有找到不会在当前目录下寻找,即使当前目录下有所需类文件。
思考:在开发时,分号是否需要?
最好不要加分号,如需访问当前目录下的所需类文件,可以用"."表示。
4、包之间的访问
*被访问的包中的类权限必须是public的
*类中的成员权限:public或者protected
*protected是为其他包中的子类提供的一种权限。protected修饰后的父类,只允许不同包中子类调用其功能,不允许其他包中创建该对象调用功能。
*权限: public protected default private
同一类中 OK OK OK OK
同一包中 OK OK OK
子类 OK OK
不同包中 OK
5、import
*简化类名;
*一个程序文件中占有一个package,可以有个improt
*用来导包中的类,不导入包中的包;
*通常写import mypack.Demo,而不写import mypack.*,为什么?
因为有时只需要访问包中一小部分类,无需将整个包中的类都导入。导包原则,用到哪个类,就导入哪个类。
6、jar包
*方便项目的携带
*方便于使用,只要在classpath设置jar路径即可
*数据库驱动,SSH框架等都是以jar包体现的。