异常的概述
异常就是代表程序出现的问题
eg:
//数组索引越界异常
int[] arr = {10, 20, 30};
System.out.println(arr[3]);//ArrayIndexOutOfBoundsException
//算数异常
int a = 10;
int b = 0;
System.out.println(a / b);//ArithmeticException
异常的体系结构
Error:代表的系统级别错误 (属于严重问题),我们开发人员不用管它。
Exception: 叫做异常,代表程序可能出现的问题。
我们通常会用 Exception 以及他的子类来封装程序出现的问题。
异常的分类
运行时异常:RuntimeException 及其子类,编译阶段不会出现异常提醒。
运行时出现的异常 (如:数组索引越界异常)
编译时异常:编译阶段就会出现异常提醒的。(如:日期解析异常)
问1:异常体系的最上层父类是谁?异常分为几类?
父类:Exception。
异常分为两类:编译时异常、运行时异常
问2:编译时异常和运行时异常的区别?
编译时异常:除了RuntimeExcpetion和他的子类,其他都是编译时异常
编译阶段需要进行处理,作用在于提醒程序员。
运行时异常:RuntimeException本身和所有子类,都是运行时,异常。
编译阶段不报错,是程序运行时出现的。
一般是由于参数传递错误带来的问题。
异常的作用
- 异常是用来查询bug的关键参考信息
- 异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况
异常的处理方式
- JVM默认的处理方式
- 自己处理(捕获异常)
- 抛出异常
1.JVM默认的处理方式
把异常的名称,异常原因及异常出现的位置等信息输出在了控制台
程序停止执行,下面的代码不会再执行了
2.自己处理(捕获异常)
目的:
当代码出现异常时,可以让程序继续往下执行。
格式:
try {
可能出现异常的代码;
}catch(异常类名变量名){
异常的处理代码;
}
练习:
int[] arr = {1, 2, 3, 4, 5, 6};
try{
//可能出现异常的代码;
System.out.println(arr[10]);//此处出现了异常,程序就会在这里创建一个ArrayIndexOutofBoundsException对象
//new ArrayIndexOutOfBoundsException();
//拿着这个对象到catch的小括号中对比,看括号中的变量是否可以接收这个对象
//如果能被按收,就表示该异常就被捕获(抓住),执行catch里面对应的代码
//当catch里面所有的代码执行完毕,继续执行try...catch体系下面的其他代码
}catch(ArrayIndexOutOfBoundsException e){
//如果出现了ArrayIndexOutofBoundsException异常,我该如何处理
System.out.println("索引越界了");
}
System.out.println("看看我执行了吗?");
3.抛出异常
1.throws
写在方法定义处,表示声明一个异常告诉调用者,使用本方法可能会有哪些异常
格式:
public void方法()throws异常类名1,异常类名2...{
...
}
编译时异常:必须要写。
运行时异常:可以不写。
2.throw
写在方法内,结束方法,手动抛出异常对象,交给调用者方法中下面的代码不再执行了
格式:
public void 方法(){
throw new NullPointerException();
}
问1:如果try中没有遇到问题,怎么执行?
问2:如果try中可能会遇到多个问题,怎么执行?
问3:如果try中遇到的问题没有被捕获,怎么执行?
问4:如果try中遇到了问题,那么try下面的其他代码还会执行吗?
1.如果try中没有遇到问题,怎么执行?
会把try里面所有的代码全部执行完毕,
不会执行catch里面的代码
2.如果try中可能会遇到多个问题,怎么执行?
会写多个catch与之对应
细节:
如果我们要捕获多个异常,这些异常中如果存在父子关系的话,那么父类一定要写在下面
了解性:
在JDK7之后,我们可以在catch中同时捕获多个异常,中间用|进行隔开
表示如果出现了A异常或者B异常的话,采取同一种处理方案
//JDK7
int[] arr = {1, 2,3,4,5,6};
try{
System.out.printin(arr[10]);//ArrayIndexOutofBoundsException
System.out.println(2/0);//ArithmeticException
String s = null;
System.out.println(s.equals("abc"));
}catch(ArrayIndexOutOfBoundsException | ArithmeticE:xception e){
System.out.println("索引越界了");
}catch(NullPointerException e){
System.out.println("空指针异常");
}catch (Exception e){
System.out.println("Exception");
3:如果try中遇到的问题没有被捕获,怎么执行?
相当于try…catch的代码白写了,最终还是会交给虚拟机进行处理。
int[]arr={1,2,3,4,5,6};
try{
System.out.println(arr[10]);//new ArrayIndexoutofBoundsException();
}catch(NullPointerException e){
System.out.println("空指针异常");
}
System.out.println("看看我执行了吗?");
4:如果try中遇到了问题,那么try下面的其他代码还会执行吗?
下面的代码就不会执行了,直接跳转到对应的catch当中,执行catch里面的语句体但是如果没有对应catch与之匹配,那么还是会交给虚拟机进行处理
int[]arr ={1,2,3,4,5,6};
try{
System.out.println(arr[10]);
System.out.println("看看我执行了吗?...try");
}catch(ArrayIndexOutofBoundsException e){
System.out.println("索引越界了");
}
System.out.println("看看我执行了吗?..·其他代码");
Throwable的成员方法
- public String getMessage() 返回此throwable的详细消息字符串
- public String toString() 返回此可抛出的简短描述
- public void printStackTrace() 把异常的错误信息输出在控制台
细节:仅仅是打印信息,不会停止程序运行
自定义异常
- 定义异常类
- 写继承关系
- 空参构造
- 带参构造
意义:就是为了让控制台的报错信息更加的见名之意
练习:
public class NameFormatException extends RuntimeException{
//技巧:
//NameFormat:当前异常的名字,表示姓名格式化问题
//Exception:表示当前类是一个异常类
//运行时:RuntimeException核心就表示由于参数错误而与致的问题
//编译时:Exception核心提醒程序员检查本地信息
public NameFormatException() {
}
public NameFormatException(String message){
super(message);
}
public void setName(String name) {
int len = name.length();
if(len < 3 || len > 10){
throw new NameFormatException(name+"格式有误,长度应该为:3~10""","
}
this.name = name;
}
//1.创建键盘录入的对象
Scanner sc = new Scanner(System.in);
//2.创建女朋友的对象
GirlFriend gf = new GirlFriend();
while (true) {
//3.接收女朋友的姓名
try{
System.out.println("请输入你心仪的女朋友的名字");
String name = sc.nextLine();
gf.setName(name);
//4.接收女朋友的年龄
System.out.println("请输入你心仪的女朋友的年龄");
String ageStr = sc.nextline();
int age = Integer.parseInt(ageStr);
gf.setAge(age);
//如果所有的数据都是正确的,那么跳出循环
break;
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (NameFormatException e) {
e.printStackTrace();
}catch (AgeOutOfBoundsException e) {
e.printStackTrace();
//5.打印
System.out.println(gf);