目录
如果try中遇到了问题,那么try下面的其他代码还会执行吗?
异常
1.异常是什么?
- 程序中可能出现的问题
2.异常体系的最上层父类是谁?异常分为几类?
- 父类:Exception。
- 异常分为两类:编译时异常、运行时异常
3.编译时异常和运行时异常的区别?
- 编译时异常:没有继承RuntimeExcpetion的异常,直接继承于Excpetion。编译阶段就会错误提示(如:日期解析异常)
- 运行时异常:RuntimeException本身和子类,编译阶段没有错误提示,运行时出现的(如:数组索引越界异常)
可以看到这个地方时报错,这就是编译时异常(在编译阶段,必须手动处理,否则代码报错)
数组越界异常,这就是运行时异常(在编译阶段是不需要处理的,是代码运行时出现的异常)
运行时异常和编译时异常的区别?
- 编译时异常:除了RuntimeExcpetion和他的子类,其他都是编译时异常。编译阶段需要进行处理,作用在于提醒程序员。
- 运行时异常:RuntimeException本身和所有子类,都是运行时异常,编译阶段不报错
异常的作用
异常作用一:异常是用来查询bug的关键参考信息
异常作用二:异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况
Student类
package youjunjie;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
if(age<18||age>40){
System.out.println("年龄超出范围");
}
else{
this.age = age;}
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
调用处调用了Student类里的代码,Student类并没有把复制的结果告诉调用者,而是直接打印在了控制台 ,调用者根本不知道赋值的结果,我们就可以用异常去解决
这个时候在控制台就会告诉异常的问题
处理异常的方式有两种:
- 使用try-catch块捕获和处理异常。可以在try块中放置可能抛出异常的代码,然后在catch块中处理异常。
- 使用throws关键字将异常抛出给上层调用者处理。在方法声明中声明可能抛出的异常,然后由调用该方法的代码去处理异常。
处理异常的目的是保证程序的稳定性和可靠性,避免程序因为异常而崩溃或出现错误。
捕获异常
try {
可能出现异常的代码;
} catch(异常类名 变量名){异常的处理代码;
}
目的:当代码出现异常时可以让程序继续往下执行。
这里是数组越界直接就报错了,我们可以使用try catch👇
如果try中没有遇到问题,怎么执行?
这个的运行结果会是什么呢?
这里把try里面所有的代码全部执行完毕,并没有执行catch里面的代码
我们再回到问题👇
如果try中没有遇到问题,怎么执行?
会把try里面所有的代码全部执行完毕,不会执行catch里面的代码(只有当出现了异常才会执行catch里面的代码)
如果try中可能会遇到多个问题,怎么执行?
但实际上System.out.println(2/0);这一句代码并没有执行
但是对于多个问题我们就要写多个与之匹配的catch
如果我们要捕获多个异常,这些异常中如果存在父子关系的话,那么父类一定要写在下面
如果try中可能会遇到多个问题,怎么执行?
会写多个catch与之对应
如果try中遇到的问题没有被捕获,怎么执行?
这里会直接报错,相当于try catch的代码白写了,最后还是会交给虚拟机进行
如果try中遇到的问题没有被捕获,怎么执行?
相当于try catch的代码白写了,最后还是会交给虚拟机进行
如果try中遇到了问题,那么try下面的其他代码还会执行吗?
如果try中遇到了问题,那么try下面的其他代码还会执行吗?
下面的代码就不会执行了,直接跳转到对应的catch当中,执行catch里面的语句体但是如果没有对应catch与之匹配,那么还是会交给拟机进行处理
异常中的常见方法
public string getMessage()
public string tostring() 返回此可抛出的简短描述
public void printstackTrace() 把异常的错误信息输出在控制台
getMessage
返回此 throwable 的详细消息字符串
tostring()
返回此可抛出的简短描述
printstackTrace()
在底层是利用system.err.println进行输出把异常的错误信息以红色字体输出在控制台
printStackTrace的结果是通过红字显示出来的
仅仅是打印信息,不会停止程序运行
抛出处理
throws
注意:写在方法定义处,表示声明一个异常告诉调用者,使用本方法可能会有哪些异常
throw
注意:写在方法内,结束方法。手动抛出异常对象,交给调用者。方法中下面的代码不再执行了
通过代码我们来了解一下throw与throws
这个时候可以得出最大值,那如果数组为null呢
是不是就会报错了?
这个时候我们可以使用throw跟throws抛出异常
也可以这样👇
也有可能数组会越界,与这个处理方法一样,下面来写一下优化后的代码
public class ExceptionDemo {
public static void main(String[] args) {
int[] arr={};
int max = 0;
try {
max = getMax(arr);
} catch (NullPointerException e) {
System.out.println("空指针异常");
}catch (ArrayIndexOutOfBoundsException e) {
System.out.println("索引越界异常");
}
System.out.println(max);
}
public static int getMax(int[] arr){
if(arr==null){
throw new NullPointerException();
}
if(arr.length==0){
throw new ArrayIndexOutOfBoundsException();
}
int max=arr[0];
for (int i = 1; i < arr.length; i++) {
if(arr[i]>max){
max=arr[i];
}
}
return max;
}
}
练习
键盘录入数据
需求:
键盘录入自己心仪的女朋友姓名和年龄。
姓名的长度在3~10之间,
年龄的范围为18-40岁
超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止。
提示:
需要考虑用户在键盘录入时的所有情况。
比如:录入年龄时超出范围,录入年龄时录入了abc等情况
先写个GirlFriend类
public class GirlFriend {
private String name;
private int age;
public GirlFriend() {
}
public GirlFriend(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
if(name.length()<3||name.length()>10){
throw new RuntimeException();
}
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
if(age<18||age>40){
throw new RuntimeException();
}
this.age = age;
}
public String toString() {
return "GirlFriend{name = " + name + ", age = " + age + "}";
}
}
再写测试类
public class ExceptionTest {
public static void main(String[] args) {
/*键盘录入自己心仪的女朋友姓名和年龄。
姓名的长度在3~10之间,
年龄的范围为18-40岁
超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止。
提示:
需要考虑用户在键盘录入时的所有情况。
比如:录入年龄时超出范围,录入年龄时录入了abc等情况*/
Scanner sc=new Scanner(System.in);
GirlFriend gf = new GirlFriend();
while (true) {
try {
System.out.println("请输入你心仪的女朋友的名字");
String name = sc.nextLine();
gf.setName(name);
System.out.println("请输入你心仪的女朋友的年龄");
String ageStr=sc.nextLine();
int age = Integer.parseInt(ageStr);
gf.setAge(age);
//如果所有的数据都是正确的,那么跳出循环
break;
} catch (NumberFormatException e) {
System.out.println("年龄的格式有误,请输入数字");
}catch (RuntimeException e) {
System.out.println("姓名的长度或年龄的范围有误");
}
}
System.out.println(gf);
}
}
自定义异常
- 定义异常类
- 写继承关系
- 空参构造
- 带参构造
意义:就是为了让控制台的报错信息更加的见名之意
将之前的练习中的优化一下,加上姓名格式异常类,年龄范围异常类
然后GirlFriend类的setAge与setName也要做相应的优化
运行结果还会有相应的提示
这一期就到这里啦!!!感谢各位观看!!!
继续努力努力再努力!!!