异常的概念:就是程序在运行时出现的不正常情况。
1.error:对于严重的,java通过Error类进行描述。对于Error一般不编写针对性的代码进行处理。
2.Exception:对于非严重的,java通过Exception类进行描述。对于Exception可以使用针对性的处理方式进行处理。但无论Error还是Exception都有一些共性的内容。比如:不正常的信息和引发的原因等。
Throwable
|------Error
|------Exception
3.异常主要分成两种异常:|-------编译时被检测异常
|-------编译时不被检测异常(运行时异常,RuntimException及其子类)
4.异常的好处:将问题进行封装,并将正常流程的代码和问题处理代码相分离,方便阅读。
异常由来:
问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述。并封装成对象。其实就是java对不正常情况进行描述后的对象体现。
异常的处理:
异常的 处理方式有两种:try或者throws。
1 try catch处理方式:
1) 为此java 提供了特有的语句进行处理:
try{
//需要被检测的代码
}catch(//异常变量){
//处理常量的代码;(处理方式)
}finally{
//一定会被执行的代码
}
提示: finally中定义的通常是关闭资源代码,因为资源必须释放,finally只有一种情况下不会执行,当执行到System.exit(0);finally不会执行。
2 ) 调用到抛异常的功能时,抛出几个,就处理几个。一个try对应多个catch。
3 ) 多个catch,父类的catch放在最下面。4 ) catch内,需要定义针对性的处理方式。不要简单的printStackTrace,输出语句。也不要不写。
5 ) 当捕获到的异常,本功能处理不了时,可以继续在catch抛出
try{
throw new AException();
}catch(AException e){
throw e;
}
6 ) 如果该异常处理不了,但并不属于该功能出现的异常。可以将异常转换后,再抛出和该功能相关的异常。或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去。当调用者知道,并处理也可以将捕获异常处理后,转换成新的异常。示例代码如下:
try{
throw new AException();
}catch(AExeption e){
throw new BException(e);//必须加上e让上一层知道发生了什么异常,“异常”链不能断。
}
7) 对捕获到的异常对象进行常见方法的操作。Stirng getMessage():获取异常的信息。jvm默认的异常处理机制,就是在调用printStackTrace方法
8) 对方声明几个,就对应有几个catch块,不要定义多余的catch块。如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。建立在进行catch处理时,catch中一定要定义具体处理方式。不要简单定义一句 e.printStackTrace(),也不要简单的就写一条输出语句。
2 throws 处理方式:
1) 声明异常时,建议声明更为具体的异常,这样处理的可以更具体
2) 当函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作。要么在内部try catch处理。要么在函数上声明让调用者处理。3) 在抛异常的时候,就会跳出到上一层代码块 (即以 {} 包含的称为一个代码块,嵌套的情况就是多层代码块),如果上一层没有处理该异常的语句,就继续往外跳,直到遇上处理该异常的语句为止。
这里所谓处理该异常的语句,就是指 try 后面的 catch (该异常) 语句和方法定义中的 throws 该异常。
4) throw 和throws关键字的区别:
throw用于抛出异常对象,后面跟的是异常对象;throw用在函数内。
throws用于抛出异常类,后面跟的异常类名,可以跟多个,用逗号隔开。throws用在函数上。
自定义异常:
因为项目中会出现特有的问题,而这些问题并未被java锁描述并封装对象。所以对这些特有的问题可以按照java问题封装的思想。将特有的问题。进行自定义的异常封装。
那么如何定义异常的信息?
因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时将异常信息传递给父类通过super语句。就可以直接通过getMessage()方法获取自定义的异常信息了。
自定义一个异常,需求:在程序中,对于除数是-1,也视为是错误的是无法进行运算的,那么就需要对这个问题进行自定义的描述。
代码如下:
public class MyException extends Exception {
public MyException(String string) {
super(string);
}
}
class Divide {
public static void main(String args[]) {
try {
System.out.println(divide(1, 0));
} catch (MyException e) {
System.out.println(e.getMessage());
}
}
static int divide(int x, int y) throws MyException {
if (y == 0) {
throw new MyException("这里有个异常");
}
return x / y;
}
}
运行结果:
这里有个异常
对比的代码:
public class MyException extends RuntimeException {
public MyException() {
super("除数不能为零");
}
}
class Divide{
public static void main(String args[]){
System.out.println(divide(1,0));
}
static int divide(int x,int y) throws MyException{
if(y==0){
throw new MyException();
}
return x/y;
}
}
运行结果为:Exception in thread "main" com.kid.Exception.MyException: 除数不能为零
at com.kid.Exception.Divide.divide(MyException.java:19)
at com.kid.Exception.Divide.main(MyException.java:14)
继承Exception原因:异常体系有一个特点:因为异常类和异常对象都被抛出。它们具备可抛性,这个可抛性是Throwable这个体系中独有特点只有这个体系中的类和对象才可以被throw和throws所操作。提示:throw也是函数结束的标志与return一样。运行时异常RuntimeException:
Exception中有一个特殊的子类异常RuntimeException运行异常。如果在函数内容抛出该异常,函数上可以不用声明,编译一样通过。如果在函数内容抛出该异常函数上可以不用声明,编译一样通过。之所以不用再函数声明,是因为不需要让调用者处理。当该异常发生,希望程序停止。因为在运行时,出现了无法继续运算的情况,希望停止程序后,对代码进行修改。提示:自定义异常时如果该异常的发生,无法继续进行运算,就让自定义异常继承RuntimeException。
异常在子父类覆盖中的实现:
1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类。
2.如果父类方法抛出多个异常,那么子类在覆盖方法时,只能抛出父类异常的子集。
3.如果子类或者接口的方法中没有异常抛出,那么子类覆盖方法时,也不可以抛出异常。如果子类方法发生了异常。就必须要进行try处理。绝不能抛。提示:在开发时界面级的异常必须处理,以给予用户友好的提示。
throw和throws的用法:
throw定义在函数内,用于抛出异常对象。
throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。