一、异常的处理方式
1.JVM默认的处理方式:
把异常的名称,异常的原因及异常出现的位置等信息输出在了控制台
程序停止执行,下面的代码不会再执行了
代码演示:
package a11exceptiondemo;
public class ExceptionDemo1 {
public static void main(String[] args) {
System.out.println("语句1");
System.out.println(2/0);//算数异常ArithmeticException
System.out.println("语句2");
System.out.println("语句3");
}
}
控制台结果:
2.自己处理(捕获异常)
格式:
try{ 可能出现异常的代码; }catch(异常类名 变量名){ 异常的处理代码; }
好处:可以让程序继续往下执行,不会停止
代码演示:
package a11exceptiondemo;
public class ExceptionDemo2 {
public static void main(String[] args) {
int[] arr={1,2,3,4,5};
try{
System.out.println(arr[10]);
//此处出现了异常,程序就会在这里创建一个ArrayIndexOutOfBoundsException对象
//new ArrayIndexOutOfBoundsException();
//拿着这个对象到catch的小括号中对比,看括号中的变量是否可以接收这个对象
//如果能被接收,就表示该异常就被捕获(抓住),执行catch里面对应的代码
//当catch里面的代码执行完毕,继续执行try...catch体系下面的其他代码
}catch(ArrayIndexOutOfBoundsException e){
//如果出现了异常如何处理
System.out.println("索引越界了");
}
System.out.println("语句1执行了吗");
}
}
运行结果:
四个问题:
1.如果try中没有遇到问题,怎么执行?
会把try里面所有的代码全部执行完毕,不会执行catch里面的代码
注意:只有当出现了异常才会执行catch里面的代码
代码演示:
package a11exceptiondemo;
public class ExceptionDemo3 {
public static void main(String[] args) {
int[] arr={1,2,3,4,5};
try{
System.out.println(arr[0]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("索引越界了");
}
System.out.println("语句1执行了吗");
}
}
运行结果:
2.如果try中可能会遇到多个问题,怎么执行?
会写多个catch与之对应
细节:如果我们要捕获多个异常,这些异常中如果存在父子关系的话,那么父类一定要写在下面
如果父类写在上面:会报如下错:
在JDK7以后,我们可以在catch中同时捕获多个异常,中间用 | 隔开
表示如果出现了A异常或者B异常的话,采取同一种解决方案
3.如果try中遇到的问题没有被捕获,怎么执行?
此时相当于try...catch中的代码白写了,最终还是会交个虚拟机进行处理
代码示范:
package a11exceptiondemo;
public class ExceptionDemo5 {
public static void main(String[] args) {
int[] arr={1,2,3,4,5};
try{
System.out.println(arr[10]);//ArrayIndexOutOfBoundsException
}catch(NullPointerException e){
System.out.println("空指针异常");
}
System.out.println("语句1执行了吗");
}
}
运行结果:
4.如果try中遇到了问题,那么try下面的其他代码还会执行吗?
如果try中遇到了问题,那么try下面的其他代码就不会执行了,直接跳转到对应的catch当中,执行catch里面的语句体,但如果没有找到对应的catch与之匹配,那么还是会交给虚拟机进行处理
Throwable的成员方法
public String getMessage()--------->返回throwable的详细信息字符串
public String toString()-------->返回此可抛出的简短描述
public void printStackTrace()------->把异常的错误信息输出在控制台
细节:
printStackTrace()方法只会打印信息,不会停止程序运行
在底层是利用System.err.println进行输出,把异常的错误信息以红色字体输出在控制台
代码示范:
package a11exceptiondemo;
public class ExceptionDemo8 {
public static void main(String[] args) {
int[] arr={1,2,3,4,5};
try {
System.out.println(arr[10]);
} catch (ArrayIndexOutOfBoundsException e) {
// String message = e.getMessage();
// System.out.println(message);//Index 10 out of bounds for length 5
// String s = e.toString();
// System.out.println(s);//java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 5
e.printStackTrace();
}
System.out.println("语句1执行了吗");
}
}
运行结果:
3.抛出异常
throws:写在方法定义处,表示声明一个异常,告诉调用者,使用本方法可能会有哪些异常
public void 方法() throws 异常类名1, 异常类名2...{
}
编译时异常必须要写
运行时异常可以不写
throw:写在方法内,结束方法,手动抛出异常对象,交给调用者,方法中下面的代码不再执行了
public void 方法(){
throw new NullPointerException
}
代码示范:
package a11exceptiondemo;
public class ExceptionDemo9 {
public static void main(String[] args) {
//定义一个方法求数组最大值
int[] arr=null;
int max=getMax(arr);
System.out.println(max);
}
public static int getMax(int[] arr) /*throws NullPointerException,ArrayIndexOutOfBoundsException*/{
//这俩都是运行时异常可以不写
if(arr==null){
//手动创建一个异常对象,并把这个异常交给方法的调用者处理
//此时方法就会结束,下面的代码不会再执行了
throw new NullPointerException();
}
if(arr.length==0){
throw new ArrayIndexOutOfBoundsException();
}
System.out.println("看看我执行了吗");
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等情况
Friend类:
package a11exceptiondemo;
public class Friend {
private String name;
private int age;
public Friend() {
}
public Friend(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
int len=name.length();
if(len<3||len>10){
throw new RuntimeException();
}
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age<18||age>40){
throw new RuntimeException();
}
this.age = age;
}
public String toString() {
return "Friend{name = " + name + ", age = " + age + "}";
}
}
测试类:
package a11exceptiondemo;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
//1.创建键盘录入的对象
Scanner sc = new Scanner(System.in);
//2.创建朋友对象
Friend f = new Friend();
while (true) {
//3.接收朋友的姓名
try {
System.out.println("请输入朋友的名字");
String name = sc.nextLine();
f.setName(name);
//4.接受朋友的年龄
System.out.println("请输入朋友的年龄");
String ageStr = sc.nextLine();
int age = Integer.parseInt(ageStr);
f.setAge(age);
//如果所有的数据都是正确的,那么跳出循环
break;
} catch (NumberFormatException e) {
System.out.println("年龄格式有误,请输入数字");
} catch (RuntimeException e) {
System.out.println("姓名的长度或年龄的范围有误");
}
}
System.out.println(f);
}
}
运行结果:
三、自定义异常
意义:就是为了让控制台的报错信息更加的见名知意
步骤:①定义异常类②写继承关系③空参构造④带参构造
代码示范:
Friend类:
package a12Test;
public class Friend {
private String name;
private int age;
public Friend() {
}
public Friend(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
int len=name.length();
if(len<3||len>10){
throw new NameForamtException(name+"格式有误,长度应该为3~10");
}
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
if(age<18||age>40){
throw new AgeOutOfBoundsException(age+"超出了范围");
}
this.age = age;
}
public String toString() {
return "Friend{name = " + name + ", age = " + age + "}";
}
}
名字格式异常类:
package a12Test;
public class NameForamtException extends RuntimeException{
public NameForamtException() {
}
public NameForamtException(String message) {
super(message);
}
}
年龄超出范围异常类:
package a12Test;
public class AgeOutOfBoundsException extends RuntimeException{
public AgeOutOfBoundsException() {
}
public AgeOutOfBoundsException(String message) {
super(message);
}
}
测试类:
package a12Test;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
//1.创建键盘录入的对象
Scanner sc = new Scanner(System.in);
//2.创建朋友对象
Friend f=new Friend();
while (true) {
//3.接收朋友的姓名
try {
System.out.println("请输入朋友的名字");
String name = sc.nextLine();
f.setName(name);
//4.接受朋友的年龄
System.out.println("请输入朋友的年龄");
String ageStr = sc.nextLine();
int age = Integer.parseInt(ageStr);
f.setAge(age);
//如果所有的数据都是正确的,那么跳出循环
break;
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (NameForamtException e) {
e.printStackTrace();
} catch (AgeOutOfBoundsException e) {
e.printStackTrace();
}
}
System.out.println(f);
}
}
运行结果: