85c91ae023e3faa5c4ea4450ac37b2b0.png

在Java编程里,异常处理是个关键部分,可很多人对它并不了解。下面就详细讲讲Java异常的相关知识。

异常的基本体系

Java里异常的父类接口是Throwable,它有两个重要实现类,分别是Error和Exception。Error代表系统级错误,像内存溢出这种情况就属于Error,是程序难以处理的。Exception是程序运行中遇到的问题,大部分异常处理都围绕它展开。

异常的分类

根据Javac对异常的分类,可分为不可检查异常和可检查异常。不可检查异常包含Error和RuntimeException及其子类,这类异常多是程序自身错误,如数组越界。可检查异常是除Error和RuntimeException之外的异常,要求程序员手动处理,必须结合try...catch...或其他方法。

public static void main(String[] args)
{
    int re = bar();
    System.out.println(re);
}
private static int bar() 
{
    try{
        return 5;
    } finally{
        System.out.println("finally");
    }
}
/*输出:
finally
5
*/

可检查异常的处理方式

处理可检查异常有几种方法。一是用try...catch...代码块,把可能出现异常的代码放try块里,catch块捕获并处理异常。二是在方法上使用throws进行异常上抛,将异常交给调用者处理。三是在方法里用throw手动抛出异常对象,根据具体情况抛出自定义异常。

public static void main(String[] args)
    {
        int result;
        
        result  =  foo();
        System.out.println(result);     /////////2
        
        result = bar();
        System.out.println(result);    /////////2
    }
    @SuppressWarnings("finally")
    public static int foo()
    {
        trz{
            int a = 5 / 0;
        } catch (Exception e){
            return 1;
        } finally{
            return 2;
        }
    }
    @SuppressWarnings("finally")
    public static int bar()
    {
        try {
            return 1;
        }finally {
            return 2;
        }
    }

try...catch...的特殊情况

在try块里,即便有break等改变执行流的语句,finally也会执行。try、catch和finally共同向同一个内存地址写入返回值,后执行的会覆盖先执行的数据,最终调用者取的是最后一次写入的值。finally中的返回值会覆盖try或catch中的,其异常也会覆盖前面的异常。

class TestException
{
    public static void main(String[] args)
    {
        int result;
        try{
            result = foo();
            System.out.println(result);           //输出100
        } catch (Exception e){
            System.out.println(e.getMessage());    //没有捕获到异常
        }
        
        
        try{
            result  = bar();
            System.out.println(result);           //输出100
        } catch (Exception e){
            System.out.println(e.getMessage());    //没有捕获到异常
        }
    }
    
    //catch中的异常被抑制
    @SuppressWarnings("finally")
    public static int foo() throws Exception
    {
        try {
            int a = 5/0;
            return 1;
        }catch(ArithmeticException amExp) {
            throw new Exception("我将被忽略,因为下面的finally中使用了return");
        }finally {
            return 100;
        }
    }
    
    //try中的异常被抑制
    @SuppressWarnings("finally")
    public static int bar() throws Exception
    {
        try {
            int a = 5/0;
            return 1;
        }finally {
            return 100;
        }
    }
}

Java异常的面试题

class TestException
{
    public static void main(String[] args)
    {
        int result;
        try{
            result = foo();
        } catch (Exception e){
            System.out.println(e.getMessage());    //输出:我是finaly中的Exception
        }
        
        
        try{
            result  = bar();
        } catch (Exception e){
            System.out.println(e.getMessage());    //输出:我是finaly中的Exception
        }
    }
    
    //catch中的异常被抑制
    @SuppressWarnings("finally")
    public static int foo() throws Exception
    {
        try {
            int a = 5/0;
            return 1;
        }catch(ArithmeticException amExp) {
            throw new Exception("我将被忽略,因为下面的finally中抛出了新的异常");
        }finally {
            throw new Exception("我是finaly中的Exception");
        }
    }
    
    //try中的异常被抑制
    @SuppressWarnings("finally")
    public static int bar() throws Exception
    {
        try {
            int a = 5/0;
            return 1;
        }finally {
            throw new Exception("我是finaly中的Exception");
        }
        
    }
}

在面试中,异常相关问题很多。比如问Java中什么是异常,简单说异常是系统或程序传递错误的方式,通过Throwable及其子类实现,结合throw、try、catch等关键字处理。还有检查型异常和非检查型异常的区别,前者需用try、catch等在编译期处理,后者则不用。

容易混淆的概念

像RuntimeException和ArrayIndexOutOfBoundsException,它们都是非检查型异常,都继承自RuntimeException。还有throw和throws,throw用于手动抛出异常对象,throws用于在方法声明时表明该方法可能抛出的异常。

大家在实际编程中,有没有遇到过特别难处理的异常情况呢?欢迎在评论区分享,觉得文章有用的话,点赞和分享一下哦。

更多推荐