JAVA 异常

32 篇文章 1 订阅

1.概念

        在现实生活中,常常会遇到很多的问题;类似的,在java中也会出现种种的不正常情况,将这些不正常情况封装成为对象,就叫做异常。简单说:异常就是问题在java中的体现。

         就像人生病了,病可以分为严重性疾病,例如:癌症;也可以分为非严重性疾病,例如:感冒,上火。类似的,在java中的异常体系(Throwable)可以分为严重性的异常(Error)和非严重性的异常(Exception)。无论Error还是Exception都具有一些共性,比如:不正常原因,引发原因;那么根据共性抽取原则,java就把这些共性抽取到父类Throwable中。

2. 异常的体系结构

        从图中可以看出所有异常类型都是内置类 Throwable 的子类,因而 Throwable 在异常类的层次结构的顶层。Throwable 分成了两个不同的分支,一个分支是Error,它表示不希望被程序捕获或者是程序无法处理的错误。另一个分支是Exception,它表示用户程序可能捕捉的异常情况或者说是程序可以处理的异常。其中异常类 Exception 又分为运行时异常(RuntimeException )和非运行时异常。Java异常又可以分为不受检查异常( Unchecked Exception )和检查异常(Checked Exception )

 3.异常之间的区别与联系

  •  Error

        Error 类对象由 Java 虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。

比如说:

        Java虚拟机运行错误(Virtual MachineError) ,当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止;还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError) 、链接错误(LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。

        对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在Java中,错误通常是使用 Error 的子类描述。

  •  Exception

        在 Exception 分支中有一个重要的子类RuntimeException(LinkageError) ,该类型的异常自动为你所编写的程序定义 ArrayIndexOutOfBoundsException(数组下标越界)、NullPointerException(空指针异常)、ArithmeticException(算术异常)、 MissingResourceException(丢失资源)、ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。

        这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;而RuntimeException 之外的异常我们统称为非运行时异常,类型上属于 Exception 类及其子类,从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException 、 SQLException 等以及用户自定义的 Exception 异常,一般情况下不自定义检查异常。

注意 :Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;Exception 通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。

4.Java异常处理机制 

java异常处理本质:抛出异常和捕获异常

  • 抛出异常

        要理解抛出异常,首先要明白什么是异常情形(exception condition),它是指阻止当前方法或作用域继续执行的问题。其次把异常情形和普通问题相区分,普通问题是指在当前环境下能得到足够的信息,总能处理这个错误。

        对于异常情形,已经无法继续下去了,因为在当前环境下无法获得必要的信息来解决问题,你所能做的就是从当前环境中跳出,并把问题提交给上一级环境,这就是抛出异常时所发生的事情。抛出异常后,会有几件事随之发生。

        首先,是像创建普通的java对象一样将使用 new 在堆上创建一个异常对象;然后,当前的执行路径(已经无法继续下去了)被终止,并且从当前环境中弹出对异常对象的引用。此时,异常处理机制接管程序,并开始寻找一个恰当的地方继续执行程序,这个恰当的地方就是异常处理程序或者异常处理器,它的任务是将程序从错误状态中恢复,使程序要换一种方式运行,要么继续运行下去。

  • 捕获异常

        在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(

exception handler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。        

        当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适的异常处理器。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。当运行时系统遍历调用栈而未找到合适的异常处理器,则运行时系统终止。同时,意味着Java程序的终止。

注意:

        对于运行时异常、错误和检查异常,Java技术所要求的异常处理方式有所不同。由于运行时异常及其子类的不可查性,为了更合理、更容易地实现应用程序,Java规定,运行时异常将由Java运行时系统自动抛出,允许应用程序忽略运行时异常。对于方法运行中可能出现的Error,当运行方法不欲捕捉时,Java允许该方法不做任何抛出声明。因为,大多数Error异常属于永远不能被允许发生的状况,也属于合理的应用程序不该捕捉的异常。

        对于所有的检查异常,Java规定:一个方法必须捕捉,或者声明抛出方法之外。也就是说,当一个方法选择不捕捉检查异常时,它必须声明将抛出异常。

5.异常处理

  • try-catch

 语法:

try
{
   // 程序代码
}catch(ExceptionName e1)
{
   //Catch 块
} 

 例子:

public class Test1 {
    public static void main(String[] args) {
        int a=12;
        int b=0;
        int c=0;
        try {
            c=a/b;
        }catch (ArithmeticException e){
            e.printStackTrace();
            System.out.println("异常为"+e);
        }
        System.out.println(c);
    }
}

 

异常两种输出方式,一种获取异常对象后用printStackTrace()方法输出;一种直接print输出异常对象

如果需要捕获多重异常,需要使用多个catch块

语法 :try{

        // 程序代码

}catch(异常类型1 异常的变量名1){

        // 程序代码

}catch(异常类型2 异常的变量名2){

        // 程序代码

}catch(异常类型3 异常的变量名3){

        // 程序代码

}

  • throw  throws

throw 语句用于抛出明显的异常。

语法:throw ThrowableInstance;

        这里的ThrowableInstance一定是 Throwable 类类型或者 Throwable 子类类型的一个对象。简单的数据类型,例如 int ,char ,以及非 Throwable 类,例如 String 或 Object ,不能用作异常。

        有两种方法可以获取 Throwable 对象:在 catch 子句中使用参数或者使用 new 操作符创建。程序执行完 throw 语句之后立即停止; throw 后面的任何语句不被执行,最邻近的 try 块用来检查它是否含有一个与异常类型匹配的 catch 语句。

throws 语句用来声明方法可能会抛出哪些异常

语法:public void 方法名(参数) throws  异常名

异常名可以父类Exception,也可以时子类,也可以自定义异常名

简单说:throws用于暴露异常;throw用于抛出异常。

  • finally

        finally里通常用来关闭资源。比如:数据库资源,IO资源等。try是一个独立的代码块,在其中定义的变量只在该变量块中有效。如果在try以外继续使用,需要在try建立引用。在try对其进行初始化。IO,Socket就会遇到。finally代码块一般都会执行到,除非前面执行了System.exit(0)。

注意:如果finally 块与一个try联合使用,finally块将在try结束之前执行。 

对异常处理的一些建议:

    (1).声明多个异常时,建议声明更为具体的异常,这样异常处理可以更加具体;

    (2).声明了几个异常,就对应几个catch块。如果多个catch块中的异常出现继承关系时,父类异常catch块放在最下面。

    (3).进行catch处理时,catch中一定要定义具体处理方式,不要简单定义一句e.printStackTrace(),也不要简单书写一条输出语句。

try, catch,finally ,return 执行顺序

  1. 执行try,catch , 给返回值赋值

  2. 执行finally

  3. return

例子:

public class Test1 {
    public static void main(String[] args) {
        int a=12;
        int b=2;
        int c=0;
        try {
            System.out.println("66666");//1
            c=a/b;
            System.out.println("我在这里");//2
            return;
        }catch (ArithmeticException e){
            e.printStackTrace();
            System.out.println("异常为"+e);//3
        }
        finally {
            System.out.println("这里也是我");//4
        }
        System.out.println(c);
    }
}

  在没有异常出现的时候,1 2 4语句都会正常运行不会收到return的影响

 

注意:在出现异常的时候,try里面异常语句的后面都不会执行,1 3 4语句执行

 6.自定义异常:

        项目中会出现特有的问题,而这些问题并未被java封装成异常对象;那么这些特有的问题可以按照java对问题封装的思想进行自定义的异常封装;这就是自定义异常。 自定义异常时,自定义异常类必须继承Exception类或其子类,如:RuntimeException。因为只有异常体系中才具有处理问题的特性。

例子:

import java.util.Scanner;

//1.编写程序接收用户输入分数信息,如果分数在0—100之间,输出成绩。如果成绩不在该范围内,抛出异常信息,提示分数必须在0—100之间。
//要求:使用自定义异常实现
public class Test4 {
    public static void main(String[] args) throws MyException {
        Scanner s = new Scanner(System.in);
        System.out.println("输入分数:");
        int score = s.nextInt();
        MyException myException = new MyException();
        try {
            myException.chen(score);
        } catch (MyException e) {
            System.out.println("输入错误!分数必须在0—100之间");
            e.printStackTrace();
            System.out.println("用点心吧!");
        }
    }
}
class MyException extends Exception{
    public void chen(int score) throws MyException{
        if(score>0&&score<100){
            System.out.println("您的成绩为:"+score);
        }
        else{
            throw new MyException();
        }
    }
}

 

 这里自定义了一个MyException异常,要注意任何自己自定义的异常类都要继承父类Exception,否则自己定义的异常类会报错。

 

总结:异常的使用,不仅仅能够使程序完成正确的事情,还能够处理未知突发事件,并发出警告,阻止破坏的扩散,大大提高代码的健壮性,适应性。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值