异常的概述
异常就是出程序运行时出现的一些错误。
所有的异常类是从 java.lang.Exception 类继承的子类。
Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error(error一般是严重的,我们无法解决的错误,如服务器宕机) 。
异常类有两个主要的子类:IOException 类和 RuntimeException 类。
JVM的默认异常处理
main函数收到这这个问题时,有两种处理方式:
a:自己将该问题处理,然后继续运行
b:自己没有针对的处理方式,只有交给调用main的jvm来处理,jvm有一个默认的异常处理机制,就将该异常进行处理,并将该异常的名称,异常的信息,异常出现的位置打印在了控制台上,同时将程序停止运行。
自己处理异常问题
异常处理的两种方式:
- try…catch…finally
try检测异常,catch捕获异常,finally释放资源(如IO流,finally是一定会执行的,就算在finally之前有return语句finally也会在return之前执行,除非System.exit(0);结束虚拟机)
try
{
// 程序代码
}catch(ExceptionName e1)
{
//Catch 块
}catch(Exception e)
{
//处理所有异常用Exception,父类引用指向子类对象
}finally{
// 程序代码
}
JDK1.7版本加了一个新用法:
try
{
// 程序代码
}catch(ExceptionName1 | ExceptionName2 e)
{
//Catch 块,这两个异常必须是不相关的异常,不能是子父类异常
}
- throw
如果一个方法没有捕获到一个检查性异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部。
也可以使用 throw 关键字抛出一个异常,无论它是新实例化的还是刚捕获到的。
下面方法的声明抛出一个 RemoteException 异常:
import java.io.*;
public class className
{
public void deposit(double amount) throws RemoteException
{
// Method implementation
throw new RemoteException();
}
//Remainder of class definition
}
一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。
例如,下面的方法声明抛出 RemoteException 和 InsufficientFundsException:
import java.io.*;
public class className
{
public void withdraw(double amount) throws RemoteException,
InsufficientFundsException
{
// Method implementation
}
//Remainder of class definition
}
throws如果抛出的是运行时异常RuntimeException,调用这方法可以不处理,抛和不抛效果一样,比如下面的例子,ArithmeticException是运行时异常,调用时不处理抛出异常编译时不会报错,throws ArithmeticException这个加不加运行结果都一样。
public static void main(String [] args){
Test a = new Test();
int x = a.div(1,0);
System.out.println();
}
private static class Test{
public int div(int a,int b) throws ArithmeticException{
return a/b;
}
}
运行结果(加不加throws ArithmeticException都一样):
但如果throws抛出的是运行时异常以外的异常,调用这个方法时必须处理,否则编译时会报错。例如throws Exception,处理可以用同时抛出,也可以用try…catch:
同时抛出:
public static void main(String [] args)throws Exception{
Test a = new Test();
int x = a.div(1,0);
System.out.println();
}
private static class Test{
public int div(int a,int b) throws Exception{
return a/b;
}
}
try……catch:
public static void main(String [] args){
Test a = new Test();
try{
int x = a.div(1,0);
}catch (Exception e){
e.printStackTrace();
}
System.out.println();
}
private static class Test{
public int div(int a,int b) throws Exception{
return a/b;
}
}
常见运行时异常
运行时异常就是编译通过,运行时抛出的异常。
常见:
- IndexOutOfBoundsException索引越界异常
- NoSuchElementException被各种访问器方法抛出,表示被请求的元素不存在
- NullPointerException空指针异常
- ClassCastException类型转换异常
- ConcurrentModificationException并发修改异常
常见方法:
- getMessage ,获取异常信息。
- toString ,错误类名+异常信息
- JVM默认处理异常的方法:printStackTrace , 错误类名+异常信息+错误位置(行号)
throws和throw的区别
throws用在方法声明后面,跟的是异常名,可以跟多个异常名,用逗号隔开表示。抛出异常,由该方法的调用者来处理
throw用在方法体内,跟的是异常对象名,只能抛出一个异常对象名表示。抛出异常,由方法体内的语句处理
final,finally和finalize的区别
final可以修饰类,方法,变量(常量),修饰类时不能被继承,修饰方法时不能被重写,修饰变量时不能被改变,修饰引用类型变量时地址值不能改变,可以改变属性值,修饰基本数据类型时不能改变值。
finally写在try catch语句用于释放资源(关闭数据库,关闭流)
finalize()是一个方法,在垃圾回收的时候调用
finally之前return
return建立了返回路径,把要返回的值装在箱子里了,然后执行finally,虽然在finally中改变了要返回的那个变量,但是要返回路径里的值没有被改变。
异常注意事项
子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。
如果父类抛出了多个异常,子类重写父类时,只能抛出相同的类或者是他的子集,子类不能抛出父类没有的异常
如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws
如何使用异常处理
原则:如果该功能内部可以将问题处理,用try,如果处理不了,交由调用者处理,这是用throws
区别:后续程序需要继续运行就try后续程序不需要继续运行就throws
如果JDK没有提供对应的异常,需要自定义异常.