1.可能造成程序崩溃的错误输入,Java使用一种称为异常处理(exception handing)的错误捕获机制处理
2.使用断言来有选择的启用检测
3.Java日志框架:当程序出错时,记录下出现的问题,
1.错误处理
在Java程序运行期间出现了一个错误,可能是由于文件包含了错误信息,或者网络连接出现了问题,或因为使用了无效的数组下标,或试图使用一个没有被赋值的对象引用而造成的
如果因为出现错误而使得某些操作没有完成;程序应该:
返回到一种安全状态,并能够让用户执行一些其他的命令
允许用户保存所有操作的结果,并以适当的方式终止程序
异常处理的任务就是将控制权从错误产生的地方转移给能够处理这种情况的错误处理器
为了能够在程序中处理异常情况,必须研究程序中可能会出现的错误和问题,以及哪类问题需要关注
1.用户输入错误
2.设备错误(硬件问题)
3.物理限制(磁盘满了,可用存储空间已被用完)
4.代码错误
在Java中,如果某个方法不能采用正常的途径完成它的任务,就可以通过另外一个路径退出方法,在这种情况下,方法并不返回任何值,而是抛出(throw)一个封装了错误信息的对象【这个方法立即退出,并不返回任何值,调用这个方法的代码也将无法继续执行,而是,异常处理机制开始搜索能够处理这种异常状况的异常处理器(exception handler)】
1.异常分类
在Java中异常对象都是派生于Throwable类的一个实例,如果Java中内置的异常类不能够满足需求,用户可以创建自己的异常类
所有异常都是由Throwable继承而来,在下层分解为Error【未检查异常】和Exception,Exception分为RuntimeException【未检查异常】和IOException【已检查异常】
编译器将核查是否为所有的已检查异常提供了异常处理器
Error:Java运行时系统内部的错误和资源耗尽错误(应用程序不应该抛出这种类型的对象)
RuntimeException:由程序导致的错误【逻辑错误】
IOException:程序本身没有问题,但由于像I/O错误这类问题导致的异常属于其他异常
派生于RuntimeException【编写代码是的逻辑错误】:
1.错误的类型转换
2.数组访问越界
3.访问空指针
不派生于RuntimeException的其他异常:
1.试图在文件尾部后面读取数据
2.试图打开一个不存在的文件
3.试图根据给定的字符串查找Class对象,而这个字符串表示的类并不存在
如果出现RuntimeException那就一定是你的问题!!!
2.声明已检查异常
如果遇到了无法处理的情况,那么Java的方法可以抛出一个异常;一个方法不仅需要告诉编译器将要返回什么值,还要告诉编译器有可能发生什么错误
例如:一段读取文件的代码知道有可能读取的文件不存在,或者内容为空,因此,试图处理文件信息的代码就需要通知编译器可能会抛出IOException类的异常
方法应该在其首部声明所有可能抛出的异常
例如:
public FileInputStream(String name)throws FileNotFoundException
这个声明表示构造器将根据给定的String参数产生一个FileInputStream对象,但是也有可能抛出一个FileNotFoundException异常,如果发生这种糟糕的情况,构造器将不会初始化一个新的FileInputStream对象,而是抛出一个FileNotFoundException类对象;如果这个方法真的抛出这样一个异常对象,运行时系统就会开始搜索异常处理器,以便知道如何处理FileNotFoundException对象
在自己编写方法时,不必将所有可能的异常都进行声明
什么时候需在方法中用throws子句声明异常,什么异常必须使用throws子句声明,有如下4中情况应该抛出异常:
1.调动一个已检查异常的方法,例如,FileInputStream构造器
2.程序运行过程中发现错误,并且利用throw语句抛出一个已检查异常
3.程序出现错误,例如,数组访问越界
4.Java虚拟机和运行时库出现的内部错误
如果出现1或2,必须告诉调用这个方法的程序员有可能抛出异常,如果没有处理器捕获这个异常,当前执行的线程就会结束
对于那些可能被别人使用的Java方法,应该根据异常规范(exception specification),在方法的首部声明这个方法可能抛出的异常;如果一个方法有可能抛出多个已检查异常,那么必须在方法的首部列出所有的异常类,每个异常类之间用逗号隔开;不需要声明Java的内部错误,(即从Error继承的错误),也不应该声明从RuntimeException继承的那些未检查异常
一个方法必须声明所有可能抛出的已检查异常,而未检查异常要么不可控(Error)要么就应该避免发是(RuntimeException)
如果在子类中覆盖了超类的一个方法,子类方法中声明的已检查异常不能比超类方法中声明的异常更通用(即子类方法中可以抛出更特定的异常,或者根本不抛出异常)【如果超类方法没有抛出已检查异常,子类也不能抛出已检查异常】
如果类中的一个方法声明将会抛出一个异常,而这个异常是某个特定类的实例时,这个方法就有可能抛出一个这个类的异常,或者这个类的任意一个子类的异常
在Java中,没有throws说明符的方法将不能抛出任何已检查异常
3.如何抛出异常
对于一个已存在的异常,将其抛出,在这种情况下:
1.找到一个合适的异常类
2.创建这个类的对象
3.将对象抛出
一旦方法抛出了异常,这个方法就不可能返回到调用者(也就是说,不必为返回的默认值或错误代码担忧)
4.创建异常类
在程序中,可能会遇到任何标准异常类都没有能够充分地描述清楚的问题,在这种情况下,创建自己的异常类;定义一个派生于Exception的类,或者派生于Exception子类的类【定义的类应该包含2个构造器,一个默认构造器;另一个是带有详细描述信息的构造器(超类Throwable的toString方法将会打印出这些详细信息,这在调试中非常有用)】
class FileFormatException extends IOException
{
public FileFormatException(){}
public FileFormatException(String gripe)
{
super(gripe);
}
}
2.捕获异常
如果某个异常发生的时候没有在任何地方进行捕获,那程序就会终止执行,并在控制台上打印出异常信息,其中包括异常的类型和堆栈的内容
想要捕获一个异常,必须设置try/catch语句块:
try
{
code
more code
}
catch(ExceptionType e)
{
handler for this type
}
如果在try语句块中的任何代码抛出了一个在catch子句中说明的异常类,那么:
1.程序将跳出try语句块的其余代码
2.程序将执行catch子句中的处理器代码
如果在try语句块中的代码没有抛出任何异常&#