Java异常实践事项

在大学项目开发中, 你有没发现自己做的项目总是出现bug,不仅仅出现bug,而且很难根据异常信息找到异常源。我当时也是非常懊恼, 可怕的是不知道怎么维护... 软件Java异常需要理解基础的知识, 在实战中较好的处理异常。Java异常基础知识tryCatchFinally语句块  本节总结Java异常在实践中的相关事项

1、 在Finally中清理资源或者使用Try-With-Resource语句

      不要在try中关闭资源、因为一旦发生异常, 将无法正常关闭资源。以下代码给出二种处理方案, Finally关闭资源、Try-With-Resource(JDK1.7出现)

/** 写数据
     * */
    public static void writeFile(File file) {
        OutputStream os=null;
        try {
             os=new FileOutputStream(file);
             String str=new String("hello gay!");
              //     os.write(str); 不编码--错误
             os.write(str.getBytes());// 按照默认的GBK编码
             os.write(5);
             os.flush();
        } catch (Exception e) {
            e.printStackTrace();

        }finally{
           try {
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        }
/** 写数据
     * */
    public static void writeFile(File file) {

               // 它将在try被执行后自动关闭,或者处理一个异常。
        try(OutputStream os=new FileOutputStream(file)) {
             String str=new String("hello gay!");
                   os.write(str.getBytes());// 按照默认的GBK编码
             os.write(5);
        } catch (Exception e) {
            e.printStackTrace();

        }

    }

2、 给出准确的异常处理信息

      尽量能更好地描述你的异常处理信息,比如用 NumberFormatException 代替 IllegalArgumentException ,避免抛出一个不具体的异常。catch语句块中子类在前、父类在后。

public void doNotDoThis() throws Exception {
   }
public void doThis() throws NumberFormatException {

}

3、记录自定义异常

为了给调用人员和维护者更清晰的异常信息、请确保在Javadoc中添加一个@throws 声明,并描述可能导致的异常情况

/**
 * This method does something extremely useful ...
 * @throws MyBusinessException if ... happens
 */
public void doSome() throws MyBusinessException {
    ...
}

4、记录异常信息

用1-2个简短的句子解释异常的原因、使用日志文件记录

try {
    new Long("abc");
} catch (NumberFormatException e) {
    log.error(new Exception("xxx",e));
}

5、最先捕获特定的异常

         把特点的、已知的异常先捕获。catch块中只有第一个匹配到异常的catch语句才会被执行,所以,如果你最先发现IllegalArgumentException,你将永远不会到达catch里处理更具体的NumberFormatException,因为它是IllegalArgumentException的一个子类。所以要首先捕获特定的异常类,并在末尾添加一些处理不是很具体异常的catch语句。子类应该在前面、父类在后面。最后一个catch可以写Exception。

public void catchMostSpecificExceptionFirst() {
    try {
        doSomething("A message");
    } catch (NumberFormatException e) {
        log.error(e);
    } catch (IllegalArgumentException e) {
        log.error(e)
    } catch(Exception){
        //使用Exception捕获不确定的、模糊的异常
      log.error(e);
    }
}

6. 不要在catch中使用Throwable

    因为所有的Exception(包括Error)都是Throwtable的子类。Error是JVM异常,我们无法预计和修改。Throwable也不够仔细。

public void doNotCatchThrowable() {
    try {
        // do something
    } catch (Throwable t) {
        // don‘t do this!
    }
}

7、不要捕获和抛出异常

或许这样看起来很nice,当它发生时记录一个异常,然后重新抛出它,以便调用者能够适当地处理它。但是这样会同时打印日志信息和异常信息。

如果你需要添加额外的信息,应该捕获异常并将其包装在一个自定义的信息中。但要确保遵循下面的第8条异常链化。

try {
    new Long("xyz");
} catch (NumberFormatException e) {
    log.error(e);
    throw e;
}
17:44:28,945 ERROR TestExceptionHandling:65 - java.lang.NumberFormatException: For input string: "xyz"
Exception in thread "main" java.lang.NumberFormatException: For input string: "xyz"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:589)
at java.lang.Long.(Long.java:965)
at com.stackify.example.TestExceptionHandling.logAndThrowException(TestExceptionHandling.java:63)
at com.stackify.example.TestExceptionHandling.main(TestExceptionHandling.java:58)

可能这样说不太清楚,举个例子假如main调用B函数、在B中调用A函数、A中发生异常, 而我们把异常交给调用者处理(main中);应该这样:A中抛出异常、B链化抛出、main中捕获并且处理、记录。

public static void main(String[] args)
{

    System.out.println("请输入2个加数");
    int result;
    try
    {
        result = add();
        System.out.println("结果:"+result);
    } catch (Exception e){
    //1、记录
     log.error(e);
    //2、处理,比如打印;
        e.printStackTrace();
    }
}
//获取输入的2个整数返回
private static List<Integer> getInputNumbers()
{
    List<Integer> nums = new ArrayList<>();
    Scanner scan = new Scanner(System.in);
    try {
        int num1 = scan.nextInt();
        int num2 = scan.nextInt();
        nums.add(new Integer(num1));
        nums.add(new Integer(num2));
    }catch(InputMismatchException immExp){
        throw immExp;
    }finally {
        scan.close();
    }
    return nums;
}

//执行加法计算
private static int add() throws Exception
{
    int result;
    try {
        List<Integer> nums =getInputNumbers();
        result = nums.get(0)  + nums.get(1);
    }catch(InputMismatchException immExp){
        throw new Exception("计算失败",immExp);  /////////////////////////////链化:以一个异常对象为参数构造新的异常对象。
    }
    return  result;
}

8 、链化--包装异常

       异常的链化可以将多个模块的异常串联起来,使得异常信息不会丢失。

     异常链化:以一个异常对象为参数构造新的异常对象。新的异对象将包含先前异常的信息。这项技术主要是异常类的一个带Throwable参数的函数来实现的。这个当做参数的异常,我们叫他根源异常(cause)。

public static void main(String[] args)
{

    System.out.println("请输入2个加数");
    int result;
    try
    {
        result = add();
        System.out.println("结果:"+result);
    } catch (Exception e){
        e.printStackTrace();
    }
}
//获取输入的2个整数返回
private static List<Integer> getInputNumbers()
{
    List<Integer> nums = new ArrayList<>();
    Scanner scan = new Scanner(System.in);
    try {
        int num1 = scan.nextInt();
        int num2 = scan.nextInt();
        nums.add(new Integer(num1));
        nums.add(new Integer(num2));
    }catch(InputMismatchException immExp){
        throw immExp;
    }finally {
        scan.close();
    }
    return nums;
}

//执行加法计算
private static int add() throws Exception
{
    int result;
    try {
        List<Integer> nums =getInputNumbers();
        result = nums.get(0)  + nums.get(1);
    }catch(InputMismatchException immExp){
        throw new Exception("计算失败",immExp);  /////////////////////////////链化:以一个异常对象为参数构造新的异常对象。
    }
    return  result;
}

/*
请输入2个加数
r 1
java.lang.Exception: 计算失败
    at practise.ExceptionTest.add(ExceptionTest.java:53)
    at practise.ExceptionTest.main(ExceptionTest.java:18)
Caused by: java.util.InputMismatchException
    at java.util.Scanner.throwFor(Scanner.java:864)
    at java.util.Scanner.next(Scanner.java:1485)
    at java.util.Scanner.nextInt(Scanner.java:2117)
    at java.util.Scanner.nextInt(Scanner.java:2076)
    at practise.ExceptionTest.getInputNumbers(ExceptionTest.java:30)
    at practise.ExceptionTest.add(ExceptionTest.java:48)
    ... 1 more

*/

附加: finally块的细节 

  • 不要在fianlly中使用return。
  • 不要在finally中抛出异常。
  • 减轻finally的任务,不要在finally中做一些其它的事情,finally块仅仅用来释放资源是最合适的。
  • 将尽量将所有的return写在函数的最后面,而不是try ... catch ... finally中。

原文地址:https://www.cnblogs.com/achievement-active/p/9310975.html

时间: 2024-11-10 16:57:01

Java异常实践事项的相关文章

Atitit.异常的设计原理与&#160;策略处理&#160;java&#160;最佳实践&#160;p93

Atitit.异常的设计原理与 策略处理 java 最佳实践 p93 1 异常方面的使用准则,答案是::2 1.1 普通项目优先使用异常取代返回值,如果开发类库方面的项目,最好异常机制与返回值都提供,由调用者决定使用哪种方式..2 1.2 优先把异常抛出到上层处理..异常本身就是为了方便把异常情况抛出到上层处理..2 1.3 对于 HYPERLINK \l _Toc6222 方法调用结果异常情况返回策略,最终会有四种策略状况,2 1.4 返回null  还是异常??2 2 异常的由来与设计3 2

深入理解 Java 异常

目录   1. 异常框架  2. 自定义异常  3. 抛出异常  4. 捕获异常  5. 异常链  6. 异常注意事项  7. 最佳实践  8. 小结  9. 参考资料 ?? 本文已归档到:「javacore」 ?? 本文中的示例代码已归档到:「javacore」 1. 异常框架 1.1. Throwable Throwable 是 Java 语言中所有错误(Error)和异常(Exception)的超类. Throwable 包含了其线程创建时线程执行堆栈的快照,它提供了 printStack

java异常面试常见题目

在Java核心知识的面试中,你总能碰到关于 处理Exception和Error的面试题.Exception处理是Java应用开发中一个非常重要的方面,也是编写强健而稳定的Java程序的关键,这自然使它成为面试题中的常客.关于Java中Error和Exception的面试题目多是关于Exception和Error的概念,如何处理Exception,以及 处理Exception时需要遵守的最佳实践等等.尽管关于多线程.垃圾回收.JVM概念和面向对象设计等方面的问题依然主宰着这类面试,你仍然需要为回答

Java注解实践

Java注解实践 注解对代码的语意没有直接影响, 他们只负责提供信息给相关的程序使用. 注解永远不会改变被注解代码的含义, 但可以通过工具对被注解的代码进行特殊处理. JDK 基本Annotation 注解 说明 @Override 重写 @Deprecated 已过时 @SuppressWarnings(value = "unchecked") 压制编辑器警告 @SafeVarargs 修饰"堆污染"警告 @FunctionalInterface Java8特有的

java 异常基础知识以及一些面试题讲解

java是面向对象设计语言,所以异常在java中也封装了成类,而我们只要知道如何处理异常就可以, 异常概述 异常:异常就是Java程序在运行过程中出现的错误. 异常由来:问题也是现实生活中一个具体事务,也可以通过java 的类的形式进行描述,并封装成对象.其实就是Java对不正常情况进行描述后的对象体现 异常分类 程序的异常:Throwable 严重问题:Error 我们不处理.这种问题一般都是很严重的,比如说内存溢出. 问题:Exception 编译期问题:不是RuntimeException

大型网站系统与Java中间件实践

大型网站系统与Java中间件实践(贯通分布式高并发高数据高访问量网站架构与实现之权威著作,九大一线互联网公司CTO联合推荐) 曾宪杰 著   ISBN 978-7-121-22761-5 2014年4月出版 定价:65.00元 340页 16开 编辑推荐 到底是本什么书,拥有这样一份作序推荐人列表:阿里集团章文嵩博士|新浪TimYang|去哪网吴永强|丁香园冯大辉|蘑菇街岳旭强|途牛汤峥嵘|豆瓣洪强宁|淘宝陈皓/林昊-- 这本书出自淘宝技术部总监之手,他也是淘宝近10年来历次技术飞跃的参与者.贡

《Java项目实践》:简单聊天程序

<Java项目实践>:简单聊天程序 由于这个简单程序,还是涉及到很多的知识点,下面我们就一点一点的来完成. 我们熟悉的QQ聊天,就有一个界面,是吧,我们自己做一个简单的聊天程序,因此我们也就需要为Client写一个界面.因此,这就是我们第一步需要完成的任务. 第一步:为Client端写一个界面 完成一个界面有两种方法,一种是使用Frame对象来完成,另外一种是继承JFrame类来完成.本项目使用第二种. 第二种继承JFrame类完成的界面的程序如下: public class ChatClie

java异常——RuntimeException和User Define Exception

1.RuntimeException public class RuntimeException { public static void main(String[] args) { // TODO Auto-generated method stub String str="123"; int temp=Integer.parseInt(str); System.out.println(temp*temp); } } 查看parseInt方法的源代码如下: public static

【Simple Java】10个关于Java异常的常见问题

这篇文章总结了十个经常被问到的JAVA异常问题: 1.检查型异常VS非检查型异常 简单的说,检查型异常是指需要在方法中自己捕获异常处理或者声明抛出异常由调用者去捕获处理: 非检查型异常指那些不能解决的异常,如除0,空指针等: 检查型异常非常重要,因为你希望使用你API接口的人知道如何处理这些异常: 举个例子,IOException是非常常见的检查型异常,RuntimeException是非检查型异常: Java的异常层级关系图如下: 2.异常管理最佳实践 如果一个异常当前能够被恰当的处理,那么应