异常处理

1异常类的继承

1.try块里声明的变量是代码块内部局部变量,它只在try块内有效,在catch块中不能访问该变量。
2.异常(Exception)和错误(Error)两种,Exception可以被捕获,而Error错误,一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,动态链接失败等,这种错误无法捕获或无法恢复,故catcha是不能捕获到Error对象,也无须在其throws子句中声明该方法可能抛出Error及其任何子类,异常的继承图:
异常类继承图
3.进行异常捕获时不仅应该把Exception类对应的catch块放在最后,而且所有的父类异常的catch块都应该排在子类异常catch块的后面(遵循先处理小异常,再处理大 异常)
4.捕获多种类型的异常时,多中异常类型之间用竖线(|)隔开,异常变量有隐式的final修饰,因此程序不能对异常变量重新赋值
代码例子:

public class MultiExceptionTest
{
    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");    //②
        }
    }
} 

5.异常处理语法结构中只有try块是必需,而catch和finally是可选的(但必需catch和finally块至少出现其中之一),catch如果有return语句,在执行return语句之前,程序还会执行finally块,但如果catch如果有System.exit(1)语句,则不会执行finally块。
代码例子:

public class FinallyTest
{
    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块里的资源回收!");
        }
    }
}

6.不要在finally块中使用如return或throw等导致方法终止的语句,一旦在finally快中使用了return或throw语句,将会导致try块,catch块中的return,throw语句失效。
代码例子:

public class FinallyFlowTest
{
    public static void main(String[] args)
        throws Exception
    {
        boolean a = test();
        System.out.println(a);
    }
    public static boolean test()
    {
        try
        {
            // 因为finally块中包含了return语句
            // 所以下面的return语句失去作用
            return true;
        }
        finally
        {
            return false;
        }
    }
}

7.java7以后,允许try关键字后紧跟一对圆括号(这里try语句相当于包含了隐式的finally,所以后面不需要有catch和finally块),圆括号里可以声明,初始化一个或多个资源,此处的资源指的是那些必须在程序结束时显示关闭的资源(比如数据库连接,网络连接),try语句在该语句结束时会自动关闭这些资源(这些资源实现类必须实现AutoCloseable或Closeable接口)
代码例子:

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

2Checked异常和Runtime异常体系

1.Checked异常需要程序显示处理(一般是通过try…catch),否则程序会产生编译错误,而Runtime异常则不要程序显示处理。
代码例子:

public class Test
{
    public static void g() throws RuntimeException
    {
        String a=null;
    }   
    public static void t() throws Exception
    {
        String a=null;
    }
    public static void main(String[] args) 
    {
        //编译通过,因为异常是UnChecked类型
        g();
        //编译不通过,因为异常是Checked类型
        //要么用try,要么用throws,编译才能通过
        t();
    }
}

3使用throw抛出异常

1.throw语句常用于catch代码快中,其抛出的不是异常类,而是异常实例,且只能抛出一个异常实例。
2用户自定义异常都应该继承Exception基类,如果希望自定义Runtime异常,则应该继承RuntimeException基类,一般需要提供两个构造器:一个是无参数的构造器,另一个是带一个字符串参数的构造器。
代码例子:

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

3.java7以后,Java编译器会执行更细致的检查,Java编译器会检查throw语句抛出异常的实际类型
代码例子:

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

4.捕获一个异常然后接着抛出另一个异常,并把原始信息保存下来,这种典型的链式处理被称为“异常链”,JDK1.4以后,所有Throwable的子类在构造器中都可以接受一个cause对象作为参数,而这个cause就来表示原始异常。
代码例子:
第一种不使用异常链处理:

public class Test
{
    public static void g()
    {
        try
        {
            String a=null;
            System.out.println(a.length());
        } 
        catch (Exception e)
        {           
            throw new RuntimeException();
        }
    }   
    public static void main(String[] args) 
    {
        System.out.println("g()方法异常信息");
        g();        
    }
}

运行结果:
**g()方法异常信息
Exception in thread main java.lang.RuntimeException**
第二种使用异常链处理:

public class Test
{
    public static void t()
    {
        try
        {
            String a=null;
            System.out.println(a.length());
        } 
        catch (Exception e)
        {           
            throw new RuntimeException(e);
        }
    }   
    public static void main(String[] args) 
    {
        System.out.println("t()方法异常信息");
        t();        
    }
}

运行结果:
**Exception in thread main java.lang.RuntimeException: java.lang.NullPointerException
Caused by: java.lang.NullPointerException**
比较这两种的运行结果了,可以看出,异常链式处理打印出了最原始的异常信息,而非异常链式处理只打印最后一个抛出的异常信息。

4Java的异常跟踪栈

1. 异常的传播规则:只要异常没有被完全捕获(包括异常没有被捕获,或异常被处理后重新抛出了新异常),异常从发生异常的方法逐渐向外传播,首先传给该方法的调用者,该方法调用者再次传给其调用者…….
代码例子:

class SelfException extends RuntimeException
{
    SelfException(){}
    SelfException(String msg)
    {
        super(msg);
    }
}
public class PrintStackTraceTest
{
    public static void main(String[] args)
    {
        firstMethod();
    }
    public static void firstMethod()
    {
        secondMethod();
    }
    public static void secondMethod()
    {
        thirdMethod();
    }
    public static void thirdMethod()
    {
        throw new SelfException("自定义异常信息");
    }
}

运行结果:
**Exception in thread ‘main’ csdn1.SelfException: 自定义异常信息
at csdn1.PrintStackTraceTest.thirdMethod(PrintStackTraceTest.java:27)
at csdn1.PrintStackTraceTest.secondMethod(PrintStackTraceTest.java:23)
at csdn1.PrintStackTraceTest.firstMethod(PrintStackTraceTest.java:19)
at csdn1.PrintStackTraceTest.main(PrintStackTraceTest.java:15)**
这篇博客参考资料
Java疯狂讲义2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值