13异常(try/catch/finally/throws/throw、自定义异常、面试题:return执行顺序)
异常
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支持多继承吗? 不支持,但是可以通过接口继承接口的方式实现类似多继承的效果