• Java异常处理


    为什么需要异常?

    以前用C写数据结构的时候,总有这样一个烦恼:比如写栈的Pop函数,除了在函数体中完成出栈的操作,还要使用一个返回值,表示出栈操作是否成功进行。

    但是呢,为了将出栈的值返回给调用者,就要用return语句。但是return又被函数状态值占用了,于是只能用指针了,这就必须给pop函数加一个指针参数,用起来很不方便。

    java内置了异常机制,函数可以尽管执行,如果出现了什么意外的事,异常就会发生,我们的程序可以通过异常来处理这些意外。这将函数的功能与函数的执行状态分离了,编写的代码更清晰。

    java异常的继承结构和分类

    java中所有的异常都是Throwable的子类,下面又分2个分支:Error和Exception。

    Error不用我们管,当Error发生时,你应该责怪java自身。java运行时,本身系统出了问题,这并不是你的代码的问题。所以我们根本不用管Error这个分支。 Error一般很少发生。    

    Exception又可以分为2类:RuntimeException和 非RuntimeException异常。

    RuntimeException异常(非检查异常)发生时,一定你的的代码写的有问题,具体说是代码的逻辑有问题,而不是语法问题,语法问题在编译时就会提示你。

    比如使用了空指针,数组下标越界,无限循环造成的StackOverflow等。当这些异常发生时,你应该尽量去修改你的代码,而不是想着去捕获他们。这些都是可以避免的。

    非RuntimeException异常(检查异常,图中深蓝色标记的),与RuntimeException相反,他们都是程序员不可避免的,比如出现执行一个IO操作,电脑可能没磁盘容量了,或者用户移除了IO设备。数据下载时,网络断开了......

    非RuntimeException异常是java异常处理中我们最关心的异常分支。

     另外:RuntimeException异常和非RuntimeException异常一个明显的区别是,如果使用Eclipse,编译器会提醒你,并强制你处理

    RuntimeException异常,而对于RuntimeException异常,编译器不会提醒你处理。

    UIManager.setLookAndFeel是Swing中设置UI感官的方法,它会抛出:ClassNotFoundException等非RuntimeException异常

    StringIndexOutOfBoundsException 是一个RuntimeException,Eclipse不会提醒你. 

    异常发生后会怎么样

    首先要明确,异常是在方法内产生的,因为方法用来操作数据,操作数据就可能发生异常。

    我们还要理解的是函数调用栈:函数的调用时以栈的形式管理的,层级调用,依次入栈。

    当在某一个代码块中发生异常后,JVM就会去这个代码块层次中寻找异常处理器(形如:try....catch...finally),如果找到了相应的处理器,则执行处理器的代码,然后跳出,执行处理器后面的代码。如果在当前方法中找不到合适的处理器,则此方法终止执行(return 语句也不会执行),JVM递归的到这个函数的调用函数去找

    一旦找到异常处理程序,则在那一层处理掉这个异常,然后,在那一层往后执行(异常在哪里被处理掉,执行流就在那里往后执行)。

    如果一直回溯到栈底都没有异常处理程序,则此线程终止。

    下面来看一个小例子:

    public static void foo1() throws Exception
    {
         foo2();
    }
        
    private static void foo2() throws Exception
    {
         throw new Exception();
            
    }
    
    
    public static void main(String []args)
    {
         try
         {
             foo1();
         } catch (Exception e){
                // TODO Auto-generated catch block
                e.printStackTrace();
         }
            
    }
        

     

     我们可以使用异常的printStackTrace()方法打印异常的堆栈信息。

                              

    在代码中处理异常

    主要要会用try...catch....finally语句。

                          

    1、catch(XXXException e)    ,在异常发生,catch匹配到XXXException时,运行时系统就会将生成的异常对象赋值给变量e.这样,通过对异常变量e分析,就可以获取异常的详细信息异常。

    2、finally主要用在异常处理器的收尾工作。关闭一些资源。比如一个文读一个件,无论成功读取,还是读取时发生异常了,最后都要关闭文件流,这个时候就要用到finally。

    3、catch语句的顺序应该从具体异常到广泛异常,从特殊异常到一般异常。

    try{
        file.read();
      }catch(EOFException e){      //EOFException是IOException的子类
                    
      }catch (IOException e){      //IOException是Exception的子类   
                   
      }catch(Exception e){
                    
                    
      }
                

    4、同一个处理块处理多个异常

    try

    {
    ... }
    catch(AException | BException e) { System.out.println("抛出AExcpetion或者BException 都会执行这个代码块") }

    5、如果子类复写了父类中一个会抛异常的方法,那么,子类的这个方法应该抛出父类相同的异常,或者是子类异常,或者不抛异常,总之要在父类异常的可控范围内。可以想一想,如果不遵循这个规则的话,那么多态就无法实现了。

    6、如果一个方法出现异常了,也没处理,它会中断执行,不会有返回值。

    7、如果在正常离开try是因为return,break ,continuer语句,则会先去执行finally,再执行他们。

    在方法中抛出异常

    如果一个方法中会抛出异常,并且这个方法本身不去处理,让调用者去决定如何处理。那么,它就必须使用throws语句在函数头进行声明它可能抛出的所有异常类型。

    声明的作用就是告知调用者:我可能会抛出一个异常,你需要做好准备。

    下面是Swing 中UIManager类中的setLookAndFeel的函数头,它声明自己会抛出的异常。

     public static void setLookAndFeel(String className)throws ClassNotFoundException,
                                                               InstantiationException,
                                                               IllegalAccessException,
                                                               UnsupportedLookAndFeelException
     {
                    
                    //...
     }
        

    主动抛出异常

    使用throw 语句,后接一个异常对象。抛出一个异常对象。

    下面是一个将参数字符串转为大写的自定义函数。

    private String toUpper(String s) throws Exception
    {
            
            if(s==null)
                throw new Exception("Paramter is null");
            else if(s.equals(""))
                throw new Exception("Empty String");
            
            else 
                return s.toUpperCase();
            
    }

    处理异常,但又抛出异常

    有时候,一个方法需要对发生的异常进行过滤,或者对调用者隐藏某些异常,只抛出调用者能理解的异常,那么,它就要对异常进行捕获处理,然后适当抛出。 

    例子函数:打印一个字符串的第一个字符

    private  void printFirst(String s) 
    {
                
            try
            {
                System.out.println(s.charAt(0));
            }catch(NullPointerException e)
            {
                throw e;   //捕获到异常,然后抛给调用者
                
            }catch(StringIndexOutOfBoundsException e)
            {
                //do nothing。自己处理,不通告调用者。
            }
            
            
                
    }

    定义自己的异常

     异常的常用方法

    e.getMessage()                打印异常的详细信息

    e.printStackTrace()           打印异常的跟踪栈

    e.getLocalizedMessage()         异常的本地化描述

    class MyException extends Exception
    {
        public MyException()
        {
            super();
        }
        
        public MyException(String msg)
        {
            super(msg);
        }
        
        
    }
  • 相关阅读:
    多层神经网络与C++实现
    反向传导算法的推导
    sizeof()和strlen()的区别与联系
    Pascal’s Triangle
    Multiply Strings
    spring boot 数据源 配置
    spring boot 静态资源。。
    spring boot 配置 beetl 视图解析器
    spring 使用junit
    spring aspectj 注解
  • 原文地址:https://www.cnblogs.com/lulipro/p/5507270.html
Copyright © 2020-2023  润新知