Excepion理解

编译时异常和运行时异常

Exception
Java将异常类Exception分为两类:运行时异常(RuntimeException,也称为未检查异常)和非运行时异常(也称为已检查异常)。运行时异常包含Java. Lang. RunTimeException类以及所有子类,除此之外的属于Exception类及其子类的所有异常都属于非运行时异常。
简单来说就是继承RuntimeEcception的异常是运行时异常,继承Exception的异常是编译时异常(运行时异常)
运行时异常(RuntimeException及其子类)属于不可查异常,即编译器不要求强制处置的异常,然而对于编译时异常(运行时异常),编译器会强制要求进行处理。
无论是运行时异常还是编译时异常,异常都出现在运行时,不要被名字误导。
运行时异常:编译阶段不会报错,运行时可能出现错误。
编译时异常;编译阶段就会报错,必须处理,否则代码不通过,不能运行。
具体关系见下图:
在这里插入图片描述

异常在Jvm中实现原理

下面通过一些代码来演示:
有这一段代码:在main方法中,实例化一个对象,通过对象调用SE类的re方法。输出两个数的相除的结果。

package com.Exception;

public class SC {
    public static void main(String[] args) {
        SE se=new SE();
        se.re(10,0);
    }
}
class SE{
    public int re(int a, int b){
        int c;
        c=a/b;
        return c;
    }

}

正常的我们知道除数不能为0,但是JVM只会执行我们的程序。但我们让除数为0时运行。在控制台就会给我们这样的异常提示:
这里是引用
这样的异常提示出来告诉了我们程序有问题的行数,还有这样的一句话:Exception in thread “main” java.lang.ArithmeticException Create breakpoint:/ by zera,其中ArithmeticException其实是一个类,既然是一个类,那么我们就可以实例化一个对象出来,然后通对象看是否能调用某些方法打印出什么。
在这里插入图片描述
当我们尝试这样做,并且运行时,控制台就出现了几乎一样的异常提示:唯独少了/ by aero
在这里插入图片描述
既然已经打印了出来,那么我们将/ by aero作为参数传进去,接着运行:
在这里插入图片描述
于是就是就出现了和开头我们一样的异常提示。但是在原代码里,main方法中没有像这样的代码,于是通过这个示例说明了,JVM先是在底层里new 了一个对象,然后通过对象调用出方法,最后才在控制台给我们显示出这样的异常提示。

异常处理方法

有下面这样一段代码:

package com.Exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class SC1 {
    public static void main(String[] arg) {
        String sd;
        int sf;
        sd = "xiaoming";
        sf = 18;
        System.out.println("姓名" + sd + "年龄" + sf);
        System.out.println("111111111111111111111");
        ArithmeticException arithmeticException = new ArithmeticException("/ by aero");
        arithmeticException.printStackTrace();
        FileInputStream fileInputStream = new FileInputStream("D:Program File");
    }

}

这段代码有两个异常:一个是运行时异常,另外一个是编译时异常,在软件里new FileInputStream(“D:Program File”);中的FileInputStream有红线标识,如果我们直接运行,可得到这样的结果;
在这里插入图片描述
这个就是编译时异常,只有异常提示,其他代码部分没有执行,说明我们必须处理,否则代码不通过,不能运行。这里说到必须对其进行捕获或声明以便抛出。
其实这就是处理异常的方法;捕获和抛出。
就像我们身边出现问题,要么自己解决要么一级一级往上报。
捕获可以理解为自己解决,抛出理解为一级一级往上报,有点类似甩锅一样。
我们将鼠标放在划红线的FileInputStream,可以找到系统也给我们了两个选择;
在这里插入图片描述
第一个就是添加异常方法标识,也就是声明的意思,第二个就是用try/catch将它围绕或者说包含起来
用上面代码处理为例:
声明以抛出:

package com.Exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class SC1 {
    public static void main(String[] arg)throws FileNotFoundException {
        String sd;
        int sf;
        sd = "xiaoming";
        sf = 18;
        System.out.println("姓名" + sd + "年龄" + sf);
        System.out.println("111111111111111111111");
        ArithmeticException arithmeticException = new ArithmeticException("/ by aero");
        arithmeticException.printStackTrace();
        FileInputStream fileInputStream = new FileInputStream("D:Program File");

    }

}

看到我们在main方法处加上了throws FileNotFoundException,然后运行程序;
在这里插入图片描述
可以看到程序能够正常运行,其他代码部分能够执行出来,说明抛出可以这样处理异常。
第二种方法:捕获——try…catch…

package com.Exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class SC1 {
    public static void main(String[] arg) {
        String sd;
        int sf;
        sd = "xiaoming";
        sf = 18;
        System.out.println("姓名" + sd + "年龄" + sf);
        System.out.println("111111111111111111111");
        ArithmeticException arithmeticException = new ArithmeticException("/ by aero");
        arithmeticException.printStackTrace();
        try {
            FileInputStream fileInputStream = new FileInputStream("D:Program File");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }

}

看到我们将==FileInputStream fileInputStream = new FileInputStream(“D:Program File”);==写在了try…catch…里面。
再次运行出来,结果是一样的。在这里插入图片描述
这两种方法处理异常后,代码在执行是JVM在底层会new一个对象,通过对象调用方法,将异常提示在控制台通知我们。

try…finally语法讲解

try…finally
有这样的有一段代码:

package com.Exception;

public class SC2 {
    public static void main(String[] args) {
        int a;
        a=10;
        try{
            System.out.println(a);
            return;
    }finally {
            System.out.println(a++);
        }
        }
}

我们不知道这是什么,但是按照我们的逻辑来思考,程序肯定会先执行finally部分,最后在try部分。毕竟要是先执行try部分,那么return之后就结束了。肯定是不符合这个语句的,
于是我们的逻辑出来的结果是这样的;在控制台输出10和11;
但其实不然,它的输出结果是这样的:
在这里插入图片描述
为什么呢,不是a++了吗, a的值应该是11了的。
为了符合try 的语法又要符合catch 的语法,
其实在运行过程中,代码部分会变成这样的:

        int a;
        a=10;
        innt b;
        b=a;
        try{
        System.out.println(a);
        return;
        }finally {
        System.out.println(b++);
        }

在JVM中编译器对我们的代码进行了优化,进行指令重排,提高了性能,也使得程序运行能够符合try和catch两个语法句。

偶尔出现的执行顺序相反简介

有这样的一段代码:

package com.Exception;

public class SC {
    public static void main(String[] args) {
        String sd;
        int sf;
        sd="xiaoming";
        sf=18;
        System.out.println("姓名"+sd+"年龄"+sf);
        System.out.println("111111111111111111111");
        ArithmeticException arithmeticException = new ArithmeticException("/ by aero");
        arithmeticException.printStackTrace();
        

    }
}

一般而言,我们理解为代码的运行顺序是从上而下,同时我们编写代码时头脑想的运行效果也是这样来预估的。上面的片段代码,按照我们的逻辑:程序会先执行两个println方法,然后再执行后面的实例化对象。最后运行出来是两行输出内容,然后是异常提示:
在这里插入图片描述
看到结果如我们想的一样。但其实不然。如果我们尝试多运行几次,会有那么几次出现这样的运行结果:
在这里插入图片描述
这样的结果与我们逻辑上的,完全相反。看到两行输出语句的内容在我们异常提示的下面。
为什么出现会出现这样的结果呢?
这是因为Java代码在编译执行的过程中,并不一定是从上到下,每句代码部分依次顺序执行的。只是因为大多数情况下。我们编写的代码运行出来和我们逻辑上是一样的,故而我们在潜移默化中,默认为代码的运行顺序是上而下。偶尔出现几次相反的结果,也不会在意。
代码的执行可以想象成操场上同一起跑线上的几个人,只是裁判员,先让一号跑多少秒,在才让2号跑多少秒,有可能继续让一号在跑多少秒,想起2号,在让2号跑。代码它是交替执行,每个代码部分执行速度不一样,先跑完就先显示出来。
也可以比喻成同时听歌和写作业,但你沉浸在写作业那一刻,你并没有听进去音乐,而你听歌的那一刻,你也没有在思考作业题。代码执行就像多个任务同时进行,但是每一个时刻只有一个任务在跑。所以说Java代码在执行过程中,并不一定是从上到下,每句代码依次顺序执行的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值