JavaSE(基础篇)——异常机制(二)

简介: JavaSE(基础篇)——异常机制(二)

2.throw

到目前为止,我们只是获取了被Java运行时系统引发的异常。然而,我们还可以用 throw 语句抛出明确的异常。


语法形式:


throw ThrowableInstance;

这里的ThrowableInstance一定是 Throwable 类类型或者 Throwable 子类类型的一个对象。简单 的数据类型,例如 int , char ,以及非 Throwable 类,例如 String 或 Object ,不能用作异常。


有两种方法可以获取 Throwable 对象:在 catch 子句中使用参数或者使用 new 操作符创建。程序执行完 throw 语句之后立即停止; throw 后面的任何语句不被执行,最邻近的 try 块用来检查它是否含有一个与异常类型匹配的 catch 语句。


如果发现了匹配的块,控制转向该语句;如果没有发现,次包围的 try 块来检查,以此类推。如果没有发现匹配的 catch 块,默认异常处理程序中断程序的执行并且打印堆栈轨迹。



class TestThrow{ 
    static void proc(){ 
        try{
            throw new NullPointerException("demo");
        }catch(NullPointerException e){ 
            System.out.println("Caught inside proc");
            throw e;
        } 
    }
    public static void main(String [] args){
        try{proc();
         }catch(NullPointerException e){ 
            System.out.println("Recaught: "+e);
        }
    } 
}


该程序两次处理相同的错误,首先, main() 方法设立了一个异常关系然后调用proc()。proc()方法设立了另一个异常处理关系并且立即抛出一个 NullPointerException 实例,NullPointerException 在 main() 中被再次捕获。


该程序阐述了怎样创建Java的标准异常对象,特别注意这一行:


throw new NullPointerException("demo");

分析:此处 new 用来构造一个 NullPointerException 实例,所有的Java内置的运行时异常有两


个构造方法:一个没有参数,一个带有一个字符串参数。


当用第二种形式时,参数指定描述异常的字符串。如果对象用作 print() 或者 println() 的参数时,该字符串被显示。这同样可以通过调用getMessage()来实现,getMessage()是由 Throwable 定义的。



3.throws

如果一个方法可以导致一个异常但不处理它,它必须指定这种行为以使方法的调用者可以保护它们自己而不发生异常。要做到这点,我们可以在方法声明中包含一个 throws 子句。


一个throws 子句列举了一个方法可能引发的所有异常类型。这对于除了 Error 或RuntimeException 及它们子类以外类型的所有异常是必要的。一个方法可以引发的所有其他类型的异常必须在 throws 子句中声明,否则会导致编译错误。



public void info() throws Exception {
 //body of method 
}

Exception是该方法可能引发的所有的异常,也可以是异常列表,中间以逗号隔开。


【例子】


class TestThrows{
    static void throw1(){
        System.out.println("Inside throw1 . ");
        throw new IllegalAccessException("demo");
    }
    public static void main(String[] args){ throw1();
    }
}

该例子中存在两个错误,首先,throw1()方法不想处理所导致的异常,因而它必须声明 throws 子句来列举可能引发的异常即 IllegalAccessException ;其次, main() 方法必须定义try/catch 语句来捕获该异常。


正确例子如下:


class TestThrows{ 
    static void throw1() throws IllegalAccessException { 
        System.out.println("Inside throw1 . ");
        throw new IllegalAccessException("demo");
    }
    public static void main(String[] args){ 
        try {
            throw1();
        }catch(IllegalAccessException e ){ 
            System.out.println("Caught " + e);
        }
    } 
}

throws抛出异常规则


1.如果是不受检查异常( unchecked exception ),即 Error 、 RuntimeException 或它们的子类,那么可以不使用 throws 关键字来声明要抛出的异常,编译仍能顺利通过,但在运行时会被系统抛出。


2.必须声明方法可抛出的任何检查异常( checked exception )。即如果一个方法可能出现受可查异常,要么用 try-catch 语句捕获,要么用 throws 子句声明将它抛出,否则会导致编译错误。


3.仅当抛出了异常,该方法的调用者才必须处理或者重新抛出该异常。当方法的调用者无力处理该异常的时候,应该继续抛出,而不是囫囵吞枣。


4.调用方法必须遵循任何可查异常的处理和声明规则。若覆盖一个方法,则不能声明与覆盖方法不同的异常。声明的任何异常必须是被覆盖方法所声明异常的同类或子类。



4.finally

当异常发生时,通常方法的执行将做一个陡峭的非线性的转向,它甚至会过早的导致方法返回。例如,如果一个方法打开了一个文件并关闭,然后退出,你不希望关闭文件的代码被异常处理机制旁路。finally 关键字为处理这种意外而设计。


finally创建的代码块在 try/catch 块完成之后另一个 try/catch 出现之前执行。


finally块无论有没有异常抛出都会执行。如果抛出异常,即使没有 catch 子句匹配,finally 也会执行。


一个方法将从一个 try/catch 块返回到调用程序的任何时候,经过一个未捕获的异常或者是一个明 确的返回语句, finally 子句在方法返回之前仍将执行。这在关闭文件句柄和释放任何在方法开始时 被分配的其他资源是很有用。


注意:finally 子句是可选项,可以有也可以无,但是每个 try 语句至少需要一个 catch 或者 finally 子句。


【例子】


class TestFinally{
    static void proc1(){
        try{System.out.println("inside proc1");
            throw new RuntimeException("demo");
        }finally{
            System.out.println("proc1's finally");
        }
    }
    static void proc2(){
        try{System.out.println("inside proc2");
            return ;
        } finally{
            System.out.println("proc2's finally");
        }
    }
    static void proc3(){
        try{
            System.out.println("inside proc3");
        }finally{
            System.out.println("proc3's finally");
        }
    }
    public static void main(String [] args){
        try{
            proc1();
        }catch(Exception e){
            System.out.println("Exception caught");
        }
        proc2();
        proc3();
    }
}

【结果】


image.png



注:如果 finally 块与一个 try 联合使用, finally 块将在 try 结束之前执行。  


try catch finally return 的执行顺序

1.执行try,catch , 给返回值赋值


2.执行finally


3.return


自定义异常

使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承 Exception 类即可。


在程序中使用自定义异常类,大体可分为以下几个步骤:


1.创建自定义异常类。


2.在方法中通过 throw 关键字抛出异常对象。


3.如果在当前抛出异常的方法中处理异常,可以使用 try-catch 语句捕获并处理;否则在方法的声明处通过 throws 关键字指明要抛出给方法调用者的异常,继续进行下一步操作。


4.在出现异常方法的调用者中捕获并处理异常。


【举例】


class MyException extends Exception {
    private int detail;
    MyException(int a){
        detail = a;
    }
    public String toString(){
        return "MyException ["+ detail + "]";
    }
}
class TestMyException{
    static void compute(int a) throws MyException{
        System.out.println("Called compute(" + a + ")");
        if(a > 10){ throw new MyException(a);
        }
        System.out.println("Normal exit!");
    }
    public static void main(String [] args){
        try{
            compute(1);
            compute(20);
        } catch(MyException me){
            System.out.println("Caught " + me);
        }
    }
}



总结

image.png

相关文章
|
1月前
|
Java 开发者
Java中的异常处理机制探究
【8月更文挑战第20天】在Java编程中,异常处理是确保程序健壮性和稳定性的重要环节。本文将深入探讨Java的异常处理机制,包括异常的分类、如何捕获和处理它们,以及在实际开发中如何有效地利用这些机制来提高代码质量和维护性。我们将一起探索异常处理的最佳实践,并讨论如何在不牺牲性能的前提下,构建更加健壮的Java应用程序。
|
4月前
|
Java 数据库连接
JAVA 特性 异常机制
当程序抛出一个异常后,从程序中导致异常的代码处跳出,Java虚拟机检测寻找和try关键字匹配的处理该异常的catch块。 如果找到,将控制权交到catch块中的代码,然后继续往下执行程序,try块中发生异常的代码不会被重新执行。 如果没有找到处理该异常的catch块,最终运行时报错。
|
监控 IDE Java
Java 基础 - 异常机制详解(三)
Java 基础 - 异常机制详解
78 1
Java 基础 - 异常机制详解(三)
|
Java 测试技术
Java 基础 - 异常机制详解(四)
Java 基础 - 异常机制详解
80 1
|
Java 程序员 数据库
【JavaSE】学习异常
【JavaSE】学习异常
|
监控 安全 Java
Java 基础 - 异常机制详解(二)
Java 基础 - 异常机制详解
91 0
|
Java 编译器 数据库连接
Java 基础 - 异常机制详解(一)
Java 基础 - 异常机制详解
102 0
|
Java 程序员 编译器
Java基础篇 - 异常机制
Java基础篇 - 异常机制
JavaSE:第九章:异常处理
JavaSE:第九章:异常处理
JavaSE:第九章:异常处理
JavaSE:第十三章:java反射机制
JavaSE:第十三章:java反射机制
101 0
JavaSE:第十三章:java反射机制