Java异常处理
一、简述
异常:就是程序在运行时出现不正常情况。
异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述。并封装成对象。其实就是java对不正常情况进行描述后的对象体现。
对于问题的划分:
- 严重的问题。
- 非严重的问题。
对于严重的,java通过Error类进行描述。对于Error一般不编写针对性前的代码对其进行处理。(已经没救了,何必管呢?)
对于非严重的,java通过Exception类进行描述。对于Exception可以使用针对性的处理方式进行处理。
无论Error或Exception都具有一些共性内容。如:不正常情况的信息,引发原因等。
Throwable
|--Error
|--Exception
二、异常的处理
java提供了特有的语句进行处理。
try
{
//需要被检测的代码;
}
catch(异常类 变量)
{
//处理异常的代码(处理方式)
}
finally
{
//一定会执行的语句
}
了解C++的都知道在C++的异常处理中并没有finally块,那么Java中为什么要有这个呢?
只因为Java的对象中没有析构函数,在C++中,即使异常抛出了,最终也会执行到析构函数。所以Java将析构函数的功能用finally来表示,就像析构函数一样,这个块无论是否抛出异常,也必将会执行到。
所以对于对象的销毁,资源的关闭等等原本写在析构函数中的东西,在Java中,我们可以将它写到finally中。
三、对捕获的异常对象进行处理
class Demo
{
int div(int a, int b) throws ArithmeticException
{
if(b < 0)
throw new ArithmeticException(); //手动通过throw关键字抛出一个自定义的异常对象
return a / b;
}
}
public class ExceptionDemo {
public static void main(String[] args) {
Demo d = new Demo();
try
{
int ret = d.div(4, 0);
System.out.println(ret);
}
catch(ArithmeticException e)
{
System.out.println("除数为0错误");
System.out.println(e.getMessage()); //by zero
System.out.println(e.toString()); //异常名称: 异常值
e.printStackTrace(); //异常名称,异常信息,异常出现的位置
//jvm默认的异常处理机制,便是在调用printStackTrace方法.
//打印异常的堆栈跟踪信息.
}
}
}
四、throw和throws的区别
- throws使用在函数上,表示该函数可能会发生异常。 throws后面跟的异常类,可以跟多个,用逗号隔开。
- throw使用在函数内,用于抛出异常的信息。
throw后跟的是异常对象。
五、多异常处理
声明异常时,建议声明更加具体的异常,这样处理可以更具体的处理。
要抛出多个异常时,throws后面用逗号分隔异常名称,要有分别处理这些异常的catch块。
在进行catch中,一定要定义具体的处理方式,不要简单的定义一句e.printStackTrace(),亦不要仅书写一条输出语句。
可以将此些异常记录日志,生成异常日志文档。
六、自定义异常
因为项目中会出现特有的一些问题,而这些问题并未被Java所描述并封装对象,所以对于这些特有的问题可以按照Java对问题封装的思想,将特有的问题,进行自定义的异常封装。
当在函数内部出现了throw抛出异常对象,那么就必须给出对应的错误处理动作。
要么在内部try catch处理,要么在函数上声明让调用者处理。
一般情况下,函数内出现异常,函数上需要声明。
如何定义异常信息?
因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时,将异常信息通过super语句传递给父类。然后就可通过getMessage()输出信息。
自定义异常必须是自定义类继承Exception。
继承Exception的原因:
异常体系有一个特点,因为异常类和异常对象都被抛出。
他们都具备可抛性,这个可抛性是Throwable这个体系中的独有特点。
只有这个体系中的类和对象,才可被throw和throws操作。
七、RuntimeException
对于异常,分两种:
- 编译时被检测的异常。
- 编译时不被检测的异常,运行时异常,RuntimeException及其子类。
RuntimeException是Exception中的一个特殊的子类异常,称为运行时异常。
如果在函数内抛出该异常,函数上可以不用声明,编译一样通过。
如果在函数上声明了该异常,调用者可以不用进行处理,编译一样通过。
之所以不用在函数上声明,是因为不需要让调用者处理。当该异常发生时,期望程序停止。因为在运行时,出现了无法继续运算的情况,期望停止程序后,对代码进行修正。
自定义异常时,如果该异常发生后,导致无法继续进行运算,就让自定义异常继承RuntimeException。
class Demo
{
int div(int a, int b)
{
if(b == 0)
throw new ArithmeticException(); //手动通过throw关键字抛出一个自定义的异常对象
if(b < 0)
throw new FuShuException("除数为负数", b); //运行期异常,无需声明throws也可编译通过
return a / b;
}
}
public class ExceptionDemo {
public static void main(String[] args) {
Demo d = new Demo();
try {
int ret = d.div(4, -1);
System.out.println("ret=" + ret);
}catch(ArithmeticException e) {
System.out.println(e.getMessage());
}
}
}