Java异常复习笔记

Java异常复习笔记

1.Java异常简单族谱

在这里插入图片描述

  Java异常的老祖宗是Throwable,它有两个儿砸Error和Exception。Error表示系统内部错误和资源耗尽错误,这部分异常发生较少。Exception主要分为RuntimeException和其他非RuntimeException,如IOException。

  RuntimeException是程序员仔细检查代码就可以规避的异常,比如空指针异常等等,Error和RuntimeException联合称为非受检异常/运行时异常,而Exception的非RuntimeException称为受检异常/编译时异常

   我们应该关心那些经常发生的异常,即受检异常。一类题太难做不来(Error);一类题简单,小心一点就好(RuntimeException)。还有一类题比较难,所以着重考虑(Exception下的非RuntimeException)。瞎理解…

  所有异常都在运行时发生。

2.异常处理方式

  受检异常必须处理,非受检异常可以不处理。异常的处理方式具体有两种,一种是自己用哪个try catch处理,另外一种方式是在方法定义后面抛出异常,交由上层处理。

第一种方式 try-catch处理

public class TwoKindHandlers {

    public static void main(String[] args) {
        
        //自己内部处理
        try {
            FileInputStream stream = new FileInputStream("");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

第二种方式 throws异常,交由上层处理

public class TwoKindHandlers {

    public static void main(String[] args) throws FileNotFoundException {
        
          FileInputStream stream = new FileInputStream("");
      
}

注释:FileInputStream的构造方法

 public FileInputStream(String name) throws FileNotFoundException {
        this(name != null ? new File(name) : null);
    }

其中FileNotFoundException为受检异常,所有必须由程序员进行处理。

在这里插入图片描述

3.throw 和 throws

  throw 的用处是用来显式抛出异常,throws的用处是用来上抛异常(异常处理方式之一)。

public class TwoKindHandlers {

    public static void main(String[] args) throws Throwable {

        //自己内部处理
        try {
            FileInputStream stream = new FileInputStream("123");
        } catch (FileNotFoundException e) {
            Throwable t = new IOException("找不到文件", e);
            throw t;
        }
    }
}

4.try-catch-finally

4.1try块

 try块并不能单独存在,必须依附catch或是finally。try语句块里面是可能产生异常的语句块,如果有受检异常,则必须处理。

4.2catch块

  catch块用于捕捉异常,catch语块可以是多个,前面的异常类型不能是后面类型的祖先一个catch语句块可以捕获多种异常,不过要求这些类型不能有继承关系。


try{
    //.........
}catch(ExceptionType1 e ){
 
 //一个catch语句块可以捕获多种异常,  但是不能有继承关系
}catch(ExceptionType2 |ExceptionType3 |ExceptionType4 e){
    
}.....
catch(ExceptionTypeN e){
    
}

4.3finally块

  finally的代码是肯定会执行的(除了System.exit函数调用),它的作用通常是用来回收资源。如下所示:

public class TwoKindHandlers {

    public static void main(String[] args) {

        FileInputStream stream=null;
        try {
            stream = new FileInputStream("123");

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally {
            if (stream!=null){
                try {
                    stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

如果有return语句,那么finally仍然会执行吗?

仍然会执行。

下面的debug的过程说明了finally语句确实执行了。

在这里插入图片描述

但是这里有一个问题,下面的代码

public class TwoKindHandlers {

    public static void main(String[] args) {

        System.out.println(demo1(0));
    }

    private static int demo1(int i){
        try {
            return i;
        }finally {
            i++;
        }
    }


}

控制台结果是

0

但是debug过程显示i 曾经是1

后来尝试用引用类型来进行测试,发现上面的代码其实类似于

public class TwoKindHandlers {
public static void main(String[] args) {

    System.out.println(demo1(0));
}

private static int demo1(int i){
    try {
        return i;
    }finally {
        int j =i;
        j++;
    }
}
}

引用类型案例如下:

public class TwoKindHandlers {
    public static void main(String[] args) {

        System.out.println(demo1(new Student()).getAge());
    }

    private static Student demo1(Student student){
        try {
            return student;
        }finally {
            student.setAge(2);
        }
    }

}

class Student{
    private int age ;

    public Student() {
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

结果为:2.

其实这里说明了两个道理:

  1. try-catch-finally 碰到 return语句,finally仍然会进行。
  2. 如果是返回值的话,该值在finally语句中会首先被拷贝一次,然后用新的值去参加运算。

不过需要强调的是

如果调用System.exit(0)函数,程序直接终止。

5.自定义异常

  自定义异常大概是两种,受检异常和非受检异常,非受检异常继承于RuntimeException,受检异常直接继承自Exception。(注意Error类是当系统内部错误或资源耗尽时才会出现,我们不要继承于它)。自定义异常按照下面的模板写,很多的异常都是下面这个模子。

public class MyException extends Exception {

    
    //显示声明无参构造函数,方便以后继承
    public MyException() {
    }

    //message 代表异常发生的原因,用String存储
    public MyException(String message) {
        super(message);
    }
    
    //cause即具体产生的异常,这里可以通过cause.getMessage()获取原因,
    //然后将原因封装到本异常里面
    //具体的效果 就是  异常 转型 
    public MyException(String message, Throwable cause) {
        super(message, cause);
    }
    
    //还有一些构造函数未展示
    
}

6.异常常见的方法


//获取异常的原因  返回String
e.getMessage();

//另开一个线程,用于打印异常的堆栈执行过程
e.printStackTrace();

7.总结

  异常的处理的目的是为了便于调试,使得程序不那么容易宕机。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CZj1iLXS-1598878876008)(D:\工具软件\Typora\MyNotes\后端学习\Java基础阶段\3.异常复习笔记.assets\image-20200831210002683.png)]

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值