栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JavaSE进阶第十三天——异常

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaSE进阶第十三天——异常

文章目录

异常

异常的概念异常的分类异常的处理自定义异常补充知识

异常 异常的概念

概念:在java代码运行过程中,遇到不正常的事件,从而导致代码运行中断的就是异常。

异常的分类

看图理解:

Throwable类下有两个类:Erro类和Exception类
Erro类:java程序执行过程中发生错误且无法解决,则退出执行。例如:java.lang.StackOverFlowErro
Exception类又分为两个类:

    Exception直接子类:称为编译时异常/受控异常/检查异常。java中规定,此类异常在java编译阶段必须处理。否则编译无法通过。RunTimeException:称为运行时异常/非受控异常/未检查异常。java中规定,运行时异常可以不在编译阶段处理也能通过编译。
异常的处理

处理异常的关键字:

    throw:抛出异常

    throws:上抛异常

    try:监控异常代码,配合catch和finally使用

    catch:捕捉异常,需要配合try使用

    finally:不论结果如何最终finally中的代码总会输出

    异常的处理方法:

    try…catch:捕捉异常

try{
	这里写要监控的代码,也就是可能出现异常的代码
}catch(这里写可能出现的异常名称 变量名){
	e.printStackTrace();//这个方法表示输出异常详细信息
	e.getMessage();//这个方法表示获取异常简单信息,注意,这是获取,不会输出
}

例如:按照控制台提示输入1~3之间任一个数字,程序将输出相应的课程名称根据键盘输入进行判断。如果输入正确,输出对应课程名称。如果输入错误,给出错误提示

public class CurriculumQuery {

    public static void main(String[] args) {
        //创建键盘扫描器
        Scanner s = new Scanner(System.in);

        //课程代号
        int cno;

        System.out.print("请输入课程代号(1~3之间的数字):");


        //判断输入是否正确,正确则输出课程,错误则输出提示信息
        try {
            cno = s.nextInt();
            judgeCno(cno);
        }catch (InputFigureException e) {

            //给出详细提示
            //e.printStackTrace();

            //给出简单提示
            System.out.println(e.getMessage());

        }finally {
            System.out.println("欢迎提出建议");
        }
    }

    
    public static void judgeCno(int cno) throws InputFigureException{
        if (cno > 3 || cno < 1 ){
            throw new InputFigureException("输入的数字不在范围内");
        }else{
            if (cno == 1){
                System.out.println("C#编程");
            }else if (cno == 2){
                System.out.println("Java编程");
            }else if (cno == 3){
                System.out.println("Python编程");
            }
        }
    }
}

class InputFigureException extends Exception{
    //无参构造
    public InputFigureException() {
    }
    //有参构造
    public InputFigureException(String message) {
        super(message);
    }
}

    throws上抛异常
    即自身不处理异常,而是将异常抛出给调用类或jvm。
    例如上面代码中的方法:
    划线处就是上抛异常,将异常抛给调用这个方法的调用者。让调用者去处理,若是调用者无法处理可以继续上抛直到抛给jvm。(我是这样理解的,应该是最多抛到jvm)
自定义异常

自定义异常步骤:

    自定义异常类需要继承一个异常类作为父类自定义异常类中的构造方法使用父类中的构造方法
补充知识
    try…catch…finally中catch和finally都必须和try在一起才能使用,否则报错。
单独catch ——> 报错
catch(){}

单独finally ——> 报错
finally{}

catch和finally ——> 报错
catch(){}finally{}
    关于finally代码块的执行顺序问题:finally代码块中的代码无论如何最后都会被执行,那么有没有例外呢?
    当然有啊!!!
    先看这个代码:
public class Test {
    public static void main(String[] args) {
        int a = 10;
        int b =0;
        int c = 0;
        try{
            c = a/b;
        }catch (Exception e){
            e.printStackTrace();
        }finally{
            System.out.println("报错了");
        }       
    }
}

看看输出结果是什么:这个时候finally代码块中的代码是执行了的。
再看看这个代码:

public class Test {
    public static void main(String[] args) {
        int a = 10;
        int b =0;
        int c = 0;
        try{
            c = a/b;
        }catch (Exception e){
            e.printStackTrace();
            System.exit(0);
        }finally{
            System.out.println("报错了");
        }

    }
}

输出结果:
可以看到,此时finally代码块中的代码就没有执行了。
System.exit(0):表示的是终止当前运行的java虚拟机。查文档可以查到。

我们再来看另一种情况:
看代码:问输出的i是多少?
答案:11

public class T {
    public static int show() {
        int i = 0;
        try{
            i = 10;
        }finally {
            i++;
        }
        return i;
    }

    public static void main(String[] args) {
        System.out.println(show());
    }
}

再看代码:
此时输出的是多少?
答案:10

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

为什么呢?
我知道肯定你们会说因为代码自上而下执行啊。当执行到return i;之后,就返回 i 结束方法了。finally不会执行。实时真是如此吗?
看看这个代码:

public class T {
    public static int show() {
        int i = 0;
        try{
            i = 10;
            return i;
        }finally {
            i++;
            System.out.println("finally输出:"+i);
        }
    }
    public static void main(String[] args) {
        System.out.println(show());
    }
}

输出结果:

显而易见,finally代码块最终还是会执行的。那到底为什么返回的是10 呢?我看了很多帖子,我不能说他们讲的不好,但是我敢说的是,我讲的更清楚。其实很简单,看图就完了:
看蓝色行,蓝色行就是当前执行行。我们通过打断点debug测试,看看代码的执行顺序。
首先,代码main方法执行,调用show()方法,这没问题吧。
进入show()方法
按照自上而下的顺序一次执行
注意,这里执行了return
继续执行finally代码块
输出11
划重点,发现没有,执行完finally代码块后回回到第7行 return i 这里。然后结束show()方法
show()方法结束,返回值赋值给o。
这时候发现,其实o变量存储的值是10。


看完流程。我们就可以得到一个结论了。
结论:在finally前面存在return的时候,return会先将值返回,然后程序继续往下执行,当finally代码块中的代码执行完毕后将会再次返回到return行执行return结束方法的功能,但此时的return不会再返回值。return再整个过程中被分为了两部分,先传值,然后等待finally代码块的执行,再结束方法。

关于finally和return的执行还有一点:finally代码块外面有return并且位置处于finally代码块之上,同时finally代码块中还有return。此时我们可以忽略finally代码块之上的return。因为最终执行并返回的是finally代码块中的return。文字很抽象,但是咱还是老办法。打断点debug。

public class Test {

        public static int show() {
            int i = 0;
            try{
                i = 10;
                return i;
            }finally {
                i++;
                System.out.println("finally输出:"+i);
                return i;
            }
        }
        public static void main(String[] args) {
            int o = show();
            System.out.println(o);
        }
}

图是在太多,我就直接标号给你们了

看顺序,你会发现第7行,也就是第4个执行的代码 return i;其实确确实实执行了,按照上面我说法,先执行的是返回值,然后代码继续向下执行。当执行到finally代码块中的 return i ;时,也就是12行时,按照上面的说法,执行完finally代码块应该掉头回到第7行执行return语句的功能结束代码。但实际上却并不是如此。当finally代码块中存在return语句的时候,此时finally代码块中的return语句后面并不会像第7行的return语句一样将返回值和结束方法功能分开执行。它就是一个正常的return语句。也就是说,finally代码块中的return不仅返回了值还结束了方法。既然结束了方法,那么自然不会再回到第7行去执行return语句。同时,我们根据debug可以知道上面的return语句时执行过的,也就是返回过值,而下面的return又返回了一次,根据执行结果我们能够看出,下面的return返回的值覆盖了上面return的值。所以照我看来,当finally代码块中存在return语句的时候。finally代码块外面的return可以视作空气,忽视掉它。

今天的知识有点绕,大家好好消化。我也要好好消化一下。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/770316.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号