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

目录
相关文章
|
缓存 Devops Shell
云效产品使用报错问题之云效代码域迁移失败,但分组已经创建,如何解决
本合集将整理呈现用户在使用过程中遇到的报错及其对应的解决办法,包括但不限于账户权限设置错误、项目配置不正确、代码提交冲突、构建任务执行失败、测试环境异常、需求流转阻塞等问题。阿里云云效是一站式企业级研发协同和DevOps平台,为企业提供从需求规划、开发、测试、发布到运维、运营的全流程端到端服务和工具支撑,致力于提升企业的研发效能和创新能力。
|
存储 前端开发 安全
《Solidity 简易速速上手小册》第9章:DApp 开发与 Solidity 集成(2024 最新版)(上)
《Solidity 简易速速上手小册》第9章:DApp 开发与 Solidity 集成(2024 最新版)
213 0
|
Linux
Linux系统中裸机按键中断的驱动方法
Linux系统中裸机按键中断的驱动方法
196 1
Linux系统中裸机按键中断的驱动方法
|
算法
代码随想录训练营day46| 139.单词拆分
代码随想录训练营day46| 139.单词拆分
149 0
|
网络协议 Unix Shell
打开windows批处理大门
打开windows批处理大门
220 0
打开windows批处理大门
|
运维 监控 Shell
Ansible自动化工具基础篇
ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。 ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架
|
数据安全/隐私保护
成功解决pdf文档加密后时间久了忘记密码—本文档有打开口令或修改口令—在线完美解决
成功解决pdf文档加密后时间久了忘记密码—本文档有打开口令或修改口令—在线完美解决
成功解决pdf文档加密后时间久了忘记密码—本文档有打开口令或修改口令—在线完美解决
|
C++
使用C++模板判断是否基本类型
使用C++模板判断是否基本类型
261 0
|
算法 Java
如何使用java语言求一个正整数的平方根?(不使用库函数)
今天的这篇文章是我在刷算法题的时候遇到的,最简单的方法是直接调用java里面的Sqrt函数,不过有时候题目中会要求我们不能使用库函数,所以在这里我们自己定义Sqrt方法。 最常见的思路有两种,第一种是二分法,第二种是牛顿的微积分思想。没错,想当年大学时候学了很久很痛苦的微积分,被我第一次派上用场了。对于这两种方法我们一个一个看。
465 0
如何使用java语言求一个正整数的平方根?(不使用库函数)
|
JavaScript 索引 容器
基于uniapp实现的交互视频demo
一个互动视频项目,播放段剧情后出现交互按钮,用户通过按钮交互,进入下一对应剧情
869 0