java8--异常处理(java疯狂讲义3复习笔记)

 

try,catch,finally,throw,throws

java将异常分为两种,Checked异常和Runtime异常.

IndexOutOfBoundsException

NumberFormatException

ArithmeticException

NullPointerException

捕获异常时,先捕获小异常,再捕获大异常,

从java7开始,一个catch块可以捕获多种类型的异常

public static void main(String[] args)
    {
        try
        {
            int a = Integer.parseInt(args[0]);
            int b = Integer.parseInt(args[1]);
            int c = a / b;
            System.out.println("您输入的两个数相除的结果是:" + c );
        }
        catch (IndexOutOfBoundsException|NumberFormatException
            |ArithmeticException ie)
        {
            System.out.println("程序发生了数组越界、数字格式异常、算术异常之一");
            // 捕捉多异常时,异常变量默认有final修饰,
            // 所以下面代码有错:
//            ie = new ArithmeticException("test");  //
        }
        catch (Exception e)
        {
            System.out.println("未知异常");
            // 捕捉一个类型的异常时,异常变量没有final修饰
            // 所以下面代码完全正确。
            e = new RuntimeException("test");    //
        }
    }

打印到控制台:
ioe.printStackTrace(System.out);

或者
ioe.printStackTrace();

 

10.2.5 使用finally回收资源

程序在try块里打开的某些物理资源(比如IO),必须显示的回收.

java的垃圾回收机制不会回收任何物理资源,垃圾回收机制只能回收堆内存中对象所占用的内存.

public static void main(String[] args)
    {
        FileInputStream fis = null;
        try
        {
            fis = new FileInputStream("a.txt");
        }
        catch (IOException ioe)
        {
            System.out.println(ioe.getMessage());
            // return语句强制方法返回,依然会执行finally
//            return ;       //// 使用exit来退出虚拟机,不会执行finally
             System.exit(1);     //
        }
        finally
        {
            // 关闭磁盘文件,回收资源 .这也是个异常处理嵌套
if (fis != null) { try { fis.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } System.out.println("执行finally块里的资源回收!"); } }

通常情况下,不要在finally快中使用return或throw等导致方法终止的语句,一旦在finally块中使用了return或throw语句,将会导致try块,catch块中的return.throw语句失效.

 

10.2.7 java7 的自动关闭资源的try语句

try后紧跟一对圆括号,里面声明或初始化一个或多个必须被显示关闭的资源.为了保证try语句可以正常的关闭资源,这些资源实现类必须实现AutoCloseable或Colseable接口,实现这两个接口就必须实现close()方法.

实现Closeable接口的close()方法只能抛出IOException,实现AutoCloseable接口的close()方法可以抛出任何异常.

public static void main(String[] args)
            throws IOException
        {
            try (
                // 声明、初始化两个可关闭的资源
                // try语句会自动关闭这两个资源。
                BufferedReader br = new BufferedReader(
                    new FileReader("src/learnJava/LearnException.java"));
                PrintStream ps = new PrintStream(new
                    FileOutputStream("a.txt")))
            {
                // 使用两个资源
                System.out.println(br.readLine());
                ps.println("庄生晓梦迷蝴蝶");
            }
        }

 

Checked异常和Runtime异常体系

所有的RuntimeException类及其子类的示例被称为Runtime异常;其他异常被称为Checked异常.

 

10.3.1 使用throws声明抛出异常

public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("b.txt");
    }

如果某段代码中调用了一个带throws声明的方法,该方法声明抛出了Checked异常,则表明该方法希望它的调用者来处理该异常.也就是说,调用该方法时,要么放在try块中显示捕获该异常,要么在另一个带throws声明抛出的方法中.

方法重写时,throws声明抛出的异常应该是父类异常的子类或同类.

大部分推荐使用Runtime异常,而不是使用Checked异常,

public static void main(String[] args){
        try{
            FileInputStream fis = new FileInputStream("b.txt");
        }catch(IOException e){
            throw new RuntimeException(e);
        }
    }

如果throw语句抛出是Checked异常,则改异常或者被调用者显示抛出,或者在try块里.

如果throw语句抛出的是Runtime异常,则该语句无需放在try块里,也无需放在带throws声明抛出的方法中:既可以用try来捕获该异常,也可以完全不理会.

10.4.2 自定义异常类.

用户自定义的异常都应该继承Exception基类,如果希望自定义Runtime异常,则应该继承RuntimeException基类,通常需要覆写有参和无参两个构造方法.

public class AuctionException extends Exception
{
    // 无参数的构造器
    public AuctionException(){}       //// 带一个字符串参数的构造器
    public AuctionException(String msg)    //
    {
        super(msg);
    }
}

throw和catch结合使用,能再次捕捉到bid方法中的异常,并对该异常进行处理

public class AuctionTest
{
    private double initPrice = 30.0;
    // 因为该方法中显式抛出了AuctionException异常,
    // 所以此处需要声明抛出AuctionException异常
    public void bid(String bidPrice)
        throws AuctionException
    {
        double d = 0.0;
        try
        {
            d = Double.parseDouble(bidPrice);
        }
        catch (Exception e)
        {
            // 此处完成本方法中可以对异常执行的修复处理,
            // 此处仅仅是在控制台打印异常跟踪栈信息。
            e.printStackTrace();
            // 再次抛出自定义异常
            throw new AuctionException("竞拍价必须是数值,"
                + "不能包含其他字符!");
        }
        if (initPrice > d)
        {
            throw new AuctionException("竞拍价比起拍价低,"
                + "不允许竞拍!");
        }
        initPrice = d;
    }
    public static void main(String[] args)
    {
        AuctionTest at = new AuctionTest();
        try
        {
            at.bid("df");
        }
        catch (AuctionException ae)
        {
            // 再次捕捉到bid方法中的异常。并对该异常进行处理
            System.err.println(ae.getMessage());
        }
    }
}

 10.4.4 java7增强的throw语句

    public static void main(String[] args)
    // Java 6认为①号代码可能抛出Exception,
    // 所以此处声明抛出Exception
//    throws Exception
    // Java 7会检查①号代码可能抛出异常的实际类型,
    // 因此此处只需声明抛出FileNotFoundException即可。
    throws FileNotFoundException
{
    try
    {
        FileInputStream fis = new FileInputStream("b.txt");
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
        throw ex;        ////        throw new RuntimeException(ex);
    }
}

或者

    public static void main(String[] args)
    // Java 6认为①号代码可能抛出Exception,
    // 所以此处声明抛出Exception
//    throws Exception
    // Java 7会检查①号代码可能抛出异常的实际类型,
    // 因此此处只需声明抛出FileNotFoundException即可。
//    throws FileNotFoundException
{
    try
    {
        FileInputStream fis = new FileInputStream("b.txt");
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
//        throw ex;        //
        throw new RuntimeException(ex);
    }
}

 

构造器如下

public class SalException extends Exception
{
    public SalException(){}
    public SalException(String msg)
    {
        super(msg);
    }
    // 创建一个可以接受Throwable参数的构造器
    public SalException(Throwable t)
    {
        super(t);
    }
}

10.5 java的异常跟踪栈

public class LearnException {
    public static void main(String[] args)
    {
        firstMethod();
    }
    public static void firstMethod()
    {
        secondMethod();
    }
    public static void secondMethod()
    {
        thirdMethod();
    }
    public static void thirdMethod()
    {
        throw new SelfException("自定义异常信息");
    }
}
class SelfException extends RuntimeException
{
    SelfException(){}
    SelfException(String msg)
    {
        super(msg);
    }
}
Exception in thread "main" learnJava.SelfException: 自定义异常信息
    at learnJava.LearnException.thirdMethod(LearnException.java:29)
    at learnJava.LearnException.secondMethod(LearnException.java:25)
    at learnJava.LearnException.firstMethod(LearnException.java:21)
    at learnJava.LearnException.main(LearnException.java:17)

1.不要过度使用异常,包括

  1.不能用异常抛出代替所有错误处理

  2.不要使用异常处理来代替流程控制.

2.不要使用过于庞大的try块

  正确的做法是,把可能出现异常的程序分别放到单独的try块中处理.

3.尽量避免使用一个catch来捕获所有异常,特别是一些关键的代码

4.不要忽略捕获到的异常

  如何处理捕获到的异常

  1.checked异常,要尽可能修复

  2.重新抛出新的异常.把当前运行环境下要做的事情尽量昨晚,然后把异常包装成当前层的异常,重新抛给上层调用者

  3.在合适的层处理异常.如果当前层不知道如何处理异常,就不要在当前从用catch捕获异常,直接使用throws声明抛出异常,让上层调用者来负责处理该异常.

 

posted @ 2017-05-31 18:44  lakeslove  阅读(1204)  评论(0编辑  收藏  举报