章十二:异常及异常处理
前言
在这一章我们将学习到异常及异常处理。它使得程序可修改、可编程,方便在不中断程序的情况下运行代码。异常都是需要处理的 ,异常处理时需要用到Try-Catch-Finally、throws之类的格式,这样的代码完整却十分繁琐,这下该怎么办呢?然而聪明的灵长类动物——人类给出了他们的答案,5000年的漫长岁月让他们进化出了明显优于其他物种的发达大脑,利用这完美的结晶,人类惊奇的发现有两类竟然不需要处理的异常,这可给代码们出了一个巨大的难题,显然,代码们并没有做好被免检的准备,代码们难道就要因此消灭了吗?哼哼,不要被代码们的表象所迷惑,代码和人类的故事才刚刚开始......
一、了解异常和异常处理
异常—表示阻止程序正常执行的错误或情况
-
在程序运行过程中,如果JVM检测出一个不可能执行的操作,就会出现运行时错误
-
在Java中,运行时错误( Runtime Error )会作为异常(对象)抛出
-
如果异常没有被处理,程序将会非正常终止
异常处理—使程序可以继续运行或者终止
-
恢复正常的程序执行
-
进行日志处理
-
以某些方式提醒用户(错误提示、对话框等)
二、Java中的异常处理机制
异常处理机制的主要组成
-
try :监控有可能产生异常的语句块
-
catch:以合理的方式捕获并处理异常
-
finally:不管有无异常,一定会执行的语句块(一般用来释放资源等)
-
throw :手动引发异常
-
throws:指定由方法引发的异常
异常处理格式
——【try-catch】示例及结果
public class ExceptionDomo{
public static int division (int num1,int num2){
语句① int result = Integer.MIN_VALUE; //赋给result一个不可能的初值,直观化
try{
语句② result = num1 / num2;
}catch(Exception e){ //捕捉一个名称为e的异常
语句③ e.peintStackTrace(); //执行打印e异常的操作
}
语句④ return result;
}
public static void main (String[] args){ //执行顺序0①②③④⑤
语句0 int result = division(5,0);
语句⑤ System.out.println("result =" + result);
}
}
——【try-catch-finally】示例及结果
public class ExceptionDemo {
public static void main (String[] args){
int num1 = 5,num2 = 0;
int result = Integer.MIN_VALUE;
try {
System.out.println("进行除法计算");
result = num1 / num2;
System.out.println("result =" + result);
}catch(ArithmeticException e) {
e.printStackTrace();
}finally {
System.out.println("除法计算结束");
}
}
}
三、catch和自定义异常
——异常类型(不)匹配
上述我们所说的是异常匹配类型的示例,那么什么是异常类型不匹配呢?以上图为例,仅把catch后结构由ArithmeticException改为InputMismatchException(或其他不是ArithmeticException的非父类异常),此时程序中断退出,像这样不适宜的类型写在catch后面的被称为异常类型不匹配,示例如下,可对比上图示例结果。
public class ExceptionDemo {
public static void main (String[] args){
int num1 = 5,num2 = 0;
int result = Integer.MIN_VALUE;
try {
System.out.println("进行除法计算");
result = num1 / num2;
System.out.println("result =" + result);
}catch(InputMismaticException e) {
e.printStackTrace();
}finally {
System.out.println("除法计算结束");
}
}
}
——多重结构
catch的多重结构目的是较为全面的捕获异常,在较不明确异常为何种异常时,选择多重catch结构,尽量遵循先子类后父类式捕捉。
import java.util.Scanner;
public class ExceptionDemo {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入整数年龄");
int age = Integer.MIN_VALUE;
try {
age = input.nextInt();
age = age / 0;
} catch (ArithmeticException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace(System.err);
}
System.out.println("输入的年龄是:" + age);
}
}
异常处理机制
try{
语句①
语句② //可能引发异常语句
语句③
} catch(Exception1 ex1){
} finally{
语句④
}
语句⑤
1、没有发生异常的执行顺序:①②③④⑤
2、异常类型匹配的执行顺序:①②④⑤
3、异常类型不匹配的执行顺序:①②④
异常声明、抛出、捕获
1、每个方法都必须声明它可能抛出的必检异常的类型,这称为声明异常
2、不要求显式声明免检异常,必检异常必须在方法头显式声明
3、建议在方法中抛出异常,在调用时解决异常
public class DivisionDemo {
public static void division(String strNum1,String strNum2)throws ArithmeticException,NumberFormatException { //在方法中抛出异常
int num1 = Integer.parseInt(strNum1);
int num2 = Integer.parseInt(strNum2);
int result = num1 / num2;
System.out.println("result =" + result);
}
public static void main(String[] args) {
try {
division("123","abc"); //谁调用谁处理
}catch(ArithmeticException | NumberFormatException e) { //多重catch结构 JDK1.7之后可用
e.printStackTrace();
}
System.out.println("程序结束");
}
}
自定义异常
自定义异常继承了Exception,方便代码在遇到不同情况时灵活书写,下面是定义了一个角色骑马的示例,当角色的生命值大于0时才可成功上马,否则失败。
public class ThrowDemo {
public static void main(String[] args) {
Hero hero = new Hero("路人甲");
try {
hero.setHealth(100);
hero.rideHorse();
}catch (LessThanZeroException e) {
e.printStackTrace();
}
}
}
class Hero{
private String name; //角色名称
private int health; //当前生命值
/**
* 英雄的骑马方法——当英雄的生命值低于0时不允许骑马
* @return
* @throws LessThanZeroException
*/
public void rideHorse() throws LessThanZeroException{
if(health > 0)
System.out.println(name + "的生命值为:" + health + "\n大于0,已成功上马");
else
throw new LessThanZeroException(health);
}
//生成name和health的get and set
public Hero(String name) {
setName(name);
}
public void setName(String name) {
this.name = name;
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
}
/**
* 自定义异常——小于零时触发
*/
public class LessThanZeroException extends Exception{
private int value;
public LessThanZeroException() {
super("生命值小于0时不能骑马");
}
public LessThanZeroException (int value) {
super("人物的生命值为" + value + "不能骑马");
}
}