1.什么是异常
在程序运行的过程中,比如发生程序运行时磁盘空间不足,工作时电脑蓝屏,网络连接中断,被加载的类不存在等等。。针对这些不正常的情况,Java语言引入了异常,以异常类的形式对这些非正常的情况进行封装,并通过异常处理机制对程序运行时发生的问题进行处理。。
public class test {
public static int divide(int x,int y){
return x/y;
}
public static void main(String[] args) {
int result=divide(4,0);
System.out.println(result);
}
}
上述代码产生了ArithmeticException的异常,这个异常只是Java异常类中的一种,在Java中还提供了大量的异常类,这些类继承自java.lang.Throwable类。。
2.Throwable类
从图中可以看出,Throwable类哎有两个直接子类Error和Exception,其中Error代表程序中的错误, Exception代表程序中产生的异常。
-
Error类称为错误类,它表示Java运行时产生的系统内部错误或资源耗尽时的错误,是比较严重的,仅靠修改程序本身是不能恢复的,如系统崩溃,虚拟机错误等。
-
Exception类称为异常类,它表示程序本身可以处理的错误。在Java程序开发中进行的异常处理,都是针对Exception类及其子类的,在Exception类的众多子类中有一个特殊的RunTimeException类,该类及其子类用于表示运行时的异常。除了此类,Exception类下所有其他的子类都用于表示编译时的异常。
Throwable类常用方法
方法申明 | 功能描述 |
---|---|
String getMessage() | 返回此throwable的详细消息字符串 |
void printStackTrace() | 将此throwable及其追踪输出至标准错误流 |
void printStackTrace(PrintStream s) | 将此throwable及其追踪输出到指定的输出流 |
3.异常的类型
3.1 编译时的异常
在Exception的子类中,除了RunTimeException类及其子类外,其他子类都是编译时的异常。
处理编译时的异常有两种方式:
(1)使用try...catch语句对异常进行捕获处理。
(2)使用throws关键字申明抛出异常,让调用者对其处理。
3.2 运行时的异常
RunTimeException类及其子类都是运行时的异常。运行时的异常是程序运行时由Java虚拟机自动进行捕获处理的,即使没有try...catch语句或使用throws关键字申明抛出,程序也能够编译通过,只是在运行过程中可能报错。。
常见的运行时异常
异常类名称 | 异常类说明 |
---|---|
java.lang.NullPointerException | 空指针异常;出现原因:调用了未经初始化的对象或者是不存在的对象。 |
java.lang.ClassNotFoundException | 指定的类找不到;出现原因:类的名称和路径加载错误;通常都是程序试图通过字符串来加载某个类时可能引发异常。 |
java.lang.NumberFormatException | 字符串转换为数字异常;出现原因:字符型数据中包含非数字型字符。 |
java.lang.IndexOutOfBoundsException | 数组角标越界异常,常见于操作数组对象时发生。 |
java.lang.IllegalArgumentException | 方法传递参数错误。 |
java.lang.ClassCastException | 数据类型转换异常。 |
java.lang.NoClassDefFoundException | 未找到类定义错误。 |
SQLException | SQL 异常,常见于操作数据库时的SQL 语句错误。 |
java.lang.InstantiationException | 实例化异常。 |
java.lang.NoSuchMethodException | 方法不存在异常。 |
注:运行时的异常一般是由于程序中的逻辑错误引起的,在程序运行时无法恢复。
4.异常处理
4.1 try...catch和finally
当程序发生异常时,会立即中止,无法继续向下执行。Java中提供了一种对异常进行处理的方式---异常捕获,目的是为了保证程序能够有效的进行。。
try{
//可能发生异常的语句
}catch (Exception类及其子类 e){
//对捕获的异常进行相应的处理
}
public class test {
public static int divide(int x,int y){
try{
return x/y;
}catch (Exception e){
System.out.println("捕获到的异常信息为:"+e.getMessage());
}
return -1;
}
public static void main(String[] args) {
int result=divide(4,0);
System.out.println(result);
int result1=divide(-1,1);
System.out.println(result1);
}
}
上述代码输出了两个-1,不好分辨那个-1是发生异常产生的,因此进行代码的修改,如下:
public class test {
public static int divide(int x,int y){
return x/y;
}
public static void main(String[] args) {
try{
int result=divide(4,0);
System.out.println(result);
}catch (Exception e){
System.out.println("程序发生异常");
}
}
}
finally关键字
try{
//可能发生异常的语句
}catch (Exception类及其子类 e){
//对捕获的异常进行相应的处理
}finally{
//无论代码是否发生异常,都会执行
}
public class test {
public static int divide(int x,int y){
return x/y;
}
public static void main(String[] args) {
try{
int result=divide(4,0);
System.out.println(result);
}catch (Exception e){
System.out.println("程序发生异常");
}finally {
System.out.println("执行finally,无论代码是否发生异常,都会执行");
}
}
}
4.2 throws关键字
在代码开发的时候,开发者通常会意识到可能出现的异常,可以直接通过try...catch对异常进行处理,但有的时候,方法中的代码是否出现异常,开发者并不明确或者不急于处理,Java中允许这种异常从当前的方法中抛出,然后后续调用者在使用时在进行对异常进行处理。。
public class test {
public static int divide(int x,int y) throws Exception{
return x/y;
}
public static void main(String[] args) throws Exception {
int result=divide(4,0);
System.out.println(result);
}
}
在调用divide()方法时,由于该方法在方法申明的时候抛出了异常,所以在调用divide()方法的时候是必须要进行处理,否则编译就会报错。。。
public class test {
public static int divide(int x,int y) throws Exception{
return x/y;
}
public static void main(String[] args) {
try{
int result=divide(4,0);
System.out.println(result);
}catch (Exception e){
System.out.println("程序发生异常");
}finally {
System.out.println("执行finally,无论代码是否发生异常,都会执行");
}
}
}
上述代码对抛出的异常进行了异常捕获处理,所以程序可以编译通过,并正常执行。。。
4.3 throw关键字
除了可以通过throws关键字抛出异常外,还可以使用throw关键字抛出异常。与throws有所不同的是,throw用在方法体中,并且抛出的是一个异常类对象,而throws关键字用在方法申明中,用来指明方法可能抛出多个异常。。
public class test {
public static void printAge(int age) throws Exception {
if(age<0){
throw new Exception("输入的年龄有误,请输入正确的年龄!!");
}else {
System.out.println("此人的年龄为:"+age);
}
}
public static void main(String[] args) {
int age=-2;
try {
printAge(age);
}catch (Exception e){
System.out.println("捕获的异常信息为:"+e.getMessage());
}
}
}
注:通过throw关键字抛出异常后,还需要throws关键字或try...catch对异常进行处理。
需要注意的是,如果throw抛出的是Error,RunTimeException或它们的子类异常对象,则无需使用throws或try...catch对异常进行处理。。
4.4 自定义异常
class DivideByMinusException extends Exception{
public DivideByMinusException(){
super();
}
public DivideByMinusException(String message){
super(message);
}
}
public class test {
public static int divide(int x,int y) throws DivideByMinusException {
int result=x/y;
if(y==0){
throw new DivideByMinusException("除数是0 !!!");
}else {
return result;
}
}
public static void main(String[] args) {
try {
divide(4,0);
}catch (Exception e){
System.out.println("捕获的异常信息为:"+e.getMessage());
}
}
}