• Java错误处理


         编写程序的过程中,我们除了实现功能外,也要保证其健壮性。其中之一就是包括对异常的处理。Java将非正常的情况分为Exception and error。其中error错误无法修复也不可捕获。异常机制已经成为判断一门编程语言是否成熟的标准。那么我们在写程序的过程中也需要写好对异常的处理机制。比如写入日志记录便于问题的排查,比如提示错误码告诉用户错误原因。虽然说异常处理的编写会有些乏味。

         Java的异常机制主要依赖于try、catch、finally、throw、throws这五个关键字。Java将异常分为Checked和Runtime异常。Checked异常是编译阶段必须被处理的异常,否则程序发生错误无法通过编译。它体现了Java的设计哲学---没有完善错误处理的代码根本不会被执行。但是大部分的方法总是不能明确地知道如何处理异常,因此一定程度上checked异常降低了程序的生产率和代码的执行效率。

    语法结构:

    try
    {
      //业务实现代码
      ....
    }
    
    catch(Exception e)
    {
       //错误处理代码
    }
    finally
    {
       //资源回收
    }
    

     

    栗子:

    public class DivTest {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            try
            {
                int a =Integer.parseInt(args[0]);
                int b =Integer.parseInt(args[1]);
                int c =a/b;
                System.out.println(c);
                
            }
            catch(IndexOutOfBoundsException ie)
            {
                System.out.println("数组越界");
            }
            catch(NumberFormatException ne)
            {
                System.out.println("数据格式异常");
            }
            catch(ArithmeticException ae)
            {
                System.out.println("算术异常");
            }
            catch(Exception e)
            {
                System.out.println("未知异常");
            }
    
        }
    
    }

    注:所有父类异常catch块都应该放在子类异常catch块的后面。

          Java7提供的多异常捕获的异常变量有隐式final修饰,用|分开。

    访问异常信息:

    所有异常对象都包含了以下方法

    getMessage()

    printStackTrace()

    printStackTrace(PrintStream s)

    getStackTrace()

    栗子:

    public class AccessExceptionMsg {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            try
            {
                FileInputStream fis = new FileInputStream("a.txt");
            }
            catch (IOException ioe)
            {
                System.out.println(ioe.getMessage());
                ioe.printStackTrace();
            }
    
        }
    
    }
    View Code

    使用finally回收资源

    public class FinallyTest {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            FileInputStream fis =null;
            try
            {
                fis = new FileInputStream("a.txt");
            }
            catch (IOException ioe)
            {
                System.out.println(ioe.getMessage());
                //return;//强制方法返回,但是一定会执行finally代码
                System.exit(1);//finally不会被执行
            }
            finally
            {
                if(fis!=null)
                {
                    try
                    {
                        fis.close();
                    }
                    catch(IOException ioe)
                    {
                        ioe.printStackTrace();
                    }
                }
                System.out.println("exe finally");
                //尽量避免在finally里写return和throw等语句,try,catch将不会被执行
            }
    
        }
    
    }
    View Code

    注:Java7增强了try语句的功能---在try后面紧跟一对括号,括号里面可以声明、初始化一个或多个资源(数据库连接,网络连接等),try语句在该语句结束时自动关闭这些资源。

    前提是这些资源类实现了AutoCloseable或Closeable接口。Java 7几乎把所有的“资源类”都进行改写,实现了AutoCloseable或Closeable接口.

    throw和throws的区别

    throws抛出异常的思路是:当前方法也不知道如何处理这种异常类型,交给上一级调用者处理。throws 声明抛出只能在方法签名中使用,抛出多个异常类用,分开。一旦用throws,程序无需用try..catch来捕获异常。例:main方法不知道如何处理异常,交给JVM处理。JVM处理异常的方法是:打印异常的跟踪栈信息,并终止程序运行。

    throw是当程序出现错误时,系统自动跑出异常。抛出的是异常实例而不是异常类,而且每次只能抛出一个异常实例。如果是checked异常,throw语句要么在try块里,显示捕获该异常,要么放在一个throws声明抛出的方法中,交给该方法的调用者处理。

    自定义异常类

    继承Exception 或Runtime异常,必须提供两个构造器,一个无参数,一个带字符串,字符串用来描述异常对象的信息。

    catch和throw结合来用

    可以用几个方法协作处理异常,例如在方法内捕获处理和调用者处理。

    public class AuctionTest {
        private double initPrice=30.0;
        public void bid(String bidPrice) throws AuctionException
        {
            double d =0.0;
            try
            {
                d=Double.parseDouble(bidPrice);
            }
            catch(Exception e)
            {
                e.printStackTrace();
                throw new AuctionException("must be a number!");
            }
            if(initPrice>d)
            {
                throw new AuctionException("lower than auction price!");
            }
            initPrice=d;
        }
        public static void main(String[] args)
        {
            AuctionTest at = new AuctionTest();
            try
            {
                at.bid("3");
                
                
            }
            catch(AuctionException ae)
            {
                System.err.println(ae.getMessage());
            }
        }
        
    
    }
    View Code

    异常链

    异常转译:捕获原始异常,抛出一个新的业务异常,新的业务异常中包含了对用户的提示信息。

    23种设计模式之一:责任链模式

    栗子:

    public calSal() throws SalException
    {
    try
    {
      // 实现工资结算的业务逻辑
      ...
    }
    catch(SQLException sqle)
    {
    //把原始异常记录下来,留给管理员
    ...
    
    throw new SalException("访问数据库出现异常");
    }
    catch(Exception e)
    {
    //把原始异常记录下来,留给管理员
    ...
    
    throw new SalException("系统出现未知异常");
    }
    public class SalException extends Exception
    {
    publlic SalException() {};
    publlic SalException(String msg) {super(msg);};
    publlic SalException(Throwable t) {super(t)};
    }
    View Code

    Java异常跟踪栈

    开发者可以通过printStackTrace()找到异常的源头。

    public class ThreadExceptionTest implements Runnable{
        public void run()
        {
            firstMethod();
        }
        public void firstMethod()
        {
            secondMethod();
        }
        public void secondMethod()
        {
            int a =5;
            int b=0;
            int c=a/b;
        }
        public static void main(String[] args)
        {
            new Thread(new ThreadExceptionTest()).start();
        }
    
    }
    
    结果:
    Exception in thread "Thread-0" java.lang.ArithmeticException: / by zero
        at exceptionHandling.ThreadExceptionTest.secondMethod(ThreadExceptionTest.java:25)
        at exceptionHandling.ThreadExceptionTest.firstMethod(ThreadExceptionTest.java:19)
        at exceptionHandling.ThreadExceptionTest.run(ThreadExceptionTest.java:15)
        at java.lang.Thread.run(Thread.java:745)

    异常处理规则

    • 使程序代码混乱最小化
    • 捕获并保留诊断信息
    • 通知合适的人员
    • 采用合适的方式结束异常活动

    不要过度使用异常,只有对外部的,不能确定和预知的运行时错误才使用异常。

    把大块的try块分割成多个可能出现异常的程序段落,并分别放于try块中,分别捕获处理.

    catch到异常后,不要忽略,采取适当措施比如:

    • 处理异常,对异常进行合适的修复,或者绕过异常继续执行,或者提示用户重新操作....
    • 重新抛出异常,抛给上层调用者,直接用throws声明抛出该异常
  • 相关阅读:
    Hadoop: No appenders could be found for logger (org.apache.hadoop.metrics2.lib.MutableMetricsFactory).解决办法
    Libnfc
    生产服务GC调优实践及基本流程总结
    万年历算法
    C#中操作Oracle时的SQL语句参数的用法
    对DataGrid的初步了解
    C#中HashTable的用法
    正则表达式
    C#动态调用WebService
    Ubuntu 故障处理笔记
  • 原文地址:https://www.cnblogs.com/flyingbee6/p/5225439.html
Copyright © 2020-2023  润新知