欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

13异常(try/catch/finally/throws/throw、自定义异常、面试题:return执行顺序)

程序员文章站 2022-05-05 14:49:24
...

异常

1.try

异常被捕获后,可以继续执行后续代码,如果未捕获,就不再执行后续代码

try: 尝试

将可能出现异常的代码放入try块中,不要将过多的代码放进try中。=,没有阅读性。

使用要求:try不能单独出现,必须结合catch或者finally或者catch-finally

情景:1.出现的异常和捕获的异常是匹配的,捕获异常,程序继续执行,不中断

2.出现的异常和捕获的异常是不匹配的,不会捕获,程序中断,不再执行

3.捕获多个异常,多个异常写多个catch块,捕获子类和父类异常时,先写子类,后写父类。

4.捕获多个异常时,我们可以统一捕获一个父类 Exception。但实际开发中不建议这样使用,因为没有阅读性可言。

Throwable两大子类: Error Exception

Exception两种子类:

1.运行时异常(RuntimException),可处理可不处理

2.检查(编译时)异常,必须处理

2.catch

catch:捕获

使用要求:不能单独出现,必须结合try

表示捕获到异常后将执行的处理代码

多个异常写多个catch块,捕获子类和父类异常时,先写子类,后写父类

3.finally

finally:最终

不管是否出现异常都执行的代码块,或者异常是否匹配到都会执行

使用要求:不能单独出现必须结合try,或者try-catch

适用场景:通常用于关闭资源或者一些必须执行的操作

finally不执行的唯一情况,退出JVM虚拟机·

System.exit(int status);

status:0表示正常退出,非0表示非正常退出,虽然表示的含义不同,但执行退出虚拟机的效果是一样的(只是为了区分jvm关闭原因)

import java.util.Scanner;
​
/**
 *  finally关键字  最终
 *  注意:不能单独出现 必须结合 try-catch 或者结合try
 *  finally中的代码 表示不管是否出现异常都执行 或者 异常是否被捕获到都执行
 *  应用场景:当我们需要关闭一些资源的时候  
 * @author asus
 *
 */
public class Test1 {
    public static void main(String[] args) {
        try {
            Scanner in = new Scanner(System.in);
            System.out.print("请输入被除数:");
            int num1 = in.nextInt();
            System.out.print("请输入除数:");
            int num2 = in.nextInt();
            System.out.println(num1+"/"+ num2 +"="+ num1/ num2);
            
        }catch(ArithmeticException e) {
                e.printStackTrace();
        }finally {
            System.out.println("感谢使用本程序!");
        }
        
    }
}

4.throws

throws:抛的复数

使用throws声明当前方法有可能出现的异常给调用者

使用位置:在方法形参列表小括号之后

使用方式:可声明多个异常,使用逗号隔开

调用者处理异常的两种情况:

  1.如果方法声明的是运行时异常(RuntimeException),那么调用者可处理也可不处理,编译也不会报错

  2.如果方法声明的是检查异常(CheckedException) 那么调用者必须处理

检查异常处理有如下两种方式:

  1.继续声明给JVM虚拟机,自己不做处理

  2.加上try-catch自行处理

5.throw

throw:抛

位置:方法体内部 可作为一条单独的语句,一条语句只能抛出一个异常

 

throw throws
生成并抛出异常 声明方法内抛出了异常
位于方法体内部,可作为单独语句使用 必须跟在方法参数列表后面,不能单独使用
抛出一个异常对象,且只能是一个 声明抛出异常类型,可以跟多个异常

6.自定义异常

当JDK提供的异常不能满足我们的开发时,我们可以自定义异常来实现需求

1.先编写异常类

2.继承父类(Exception、Throwable、RuntimeException)都可以

3.编写构造方法,传入异常信息

4.在代码中抛出自定义异常

public class AgeException extends Exception{
​
    private static final long serialVersionUID = 1L; // 序列化ID 自动生成
​
    public AgeException(String message) {
        super(message);
    }
}
public class SexException extends RuntimeException{
​
    private static final long serialVersionUID = 1L;
    public SexException(String message) {
        super(message);
    }
}   
public class Person {
    private String name;
    private int age;
    private String sex;
    public int getAge() {
        return age;
    }
    public void setAge(int age) throws AgeException {
        if(age > 0 && age <= 130) {
            this.age = age;
        }else {
            throw new AgeException("年龄不合适");
        }
    }
    
    public String getSex() {
        return sex;
    }
​
    public void setSex(String sex) {
        if(sex.equals("男") || sex.equals("女")) {
            this.sex = sex;
        }else {
            throw new SexException("性别不合适");
        }
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    public static void main(String[] args) {
        Person p1 = new Person();
        try {
            p1.setAge(111);
        } catch (AgeException e) {
            e.printStackTrace();
        }
        p1.setSex("男");
    }
}

面试题:try-catch块中存在return语句,是否还执行finally块? 如果执行,说出执行顺序

详细链接:https://blog.csdn.net/zitian246/article/details/107966022 

try语句在返回前,将其他所有的操作执行完(未考虑try出现异常的情况,出现异常时执行catch,规则与其相同),保留好要返回的值,而后转入执行finally中的语句,而后分为以下三种情况:

情况一:如果finally中有return语句,则会将try中的return语句"覆盖"掉(异常在返回值之前除外,此时不执行try中的return语句),直接执行finally中的return语句,得到返回值,这样便无法的得到try之前保留好的返回值

情况二:如果finally中没有return语句,也没有改变要返回的值,则执行完finally中的语句后,会接着执行try中的return语句,返回之前保留的值

情况三如果finally中没有return语句,但是改变了要返回的值,这里优点类似于引用传递和值传递的区别,分以下两种情况:

        a)如果return的数据是基本数据类型或文本字符串,则在finally中对该基本数据的改变不起作用,try中的return语句依然会返回进入finally块之前保留的值

        b)如果return的数据类型是引用数据类型,而在finally中对该引用数据类型的属性值的改变起作用,try中的return语句返回的值就是在finally中改变后的该属性的值。

补充:出现异常捕获时,执行catch语句,其规则与try中相同。

任何执行try 或者catch中的return语句之前,都会先执行finally语句

 每日问题

1.异常的体系结构,写出三个父类

2.try-catch-finally-throw-throws关键字分别用途是什么?

3.RunTimeException和CheckedException有在处理上有什么不同?

4.try-catch-finally中 如果try中已经return了值 那么finally中对返回值的操作会不会改变返 回值?

5.finally不执行的唯一情况是什么?

6.继承中实现多态的主要方式是什么?两种

7.throw和throws的区别

8.自定义异常的步骤

9.静态方法中如何访问实例属性和方法?

10.java支持多继承吗?

解答

1.异常的体系结构,写出三个父类

     Throwable Exception Error

2.try-catch-finally-throw-throws关键字分别用途是什么?

    try 可能出现异常的代码

    catch 捕获异常

    finally 不管是否出现异常都将执行的代码

    throw 抛出一个异常

    throws 声明异常,可以声明多个

3.RunTimeException和CheckedException有在处理上有什么不同?

    RuntimeException 不是必须处理

    CheckedException 必须处理 继续声明给JVM虚拟机 或者 try-catch处理

4.try-catch-finally中 如果try中已经return了值 那么finally中对返回值的操作会不会改变返 回值?

5.finally不执行的唯一情况是什么?

    System.exit(int status); status 为0表示正常退出 非0 表示非正常退出 效果都一样

6.继承中实现多态的主要方式是什么?两种

    父类作为形参 父类作为返回值

7.throw和throws的区别

    throw是在方法体内部单独作为一条语句使用 抛出异常

    throws声明异常,写在形参列表之后 可以声明多个 多个之间逗号隔开

8.自定义异常的步骤

    编写异常类

    继承父类(Throwable,Exception,RuntimeException)

    编写构造方法 方法中抛出自定义异常

9.静态方法中如何访问实例属性和方法? 不能,必须先new对象,然后通过对象名. 访问

10.java支持多继承吗? 不支持,但是可以通过接口继承接口的方式实现类似多继承的效果