异常
异常指的是导致程序中断执行的一直指令流。
public static void main(String[] args) {
System.out.println("======start=====");
System.out.println(10 / 0);
System.out.println("======end=====");
}
在程序出错之后,会中断执行,为了保证程序出现非致命错误之后程序依然可以正常完成,所以需要一个完善的异常处理机制,保证程序的顺利执行。
异常的处理
在java中,如果要进行异常的处理,可以使用:try,catch,finally这几个关键字来完成,基本结果:
try{
//可能出现的异常语句
}catch(异常的类型 异常对象){
//异常处理
}catch(异常的类型 异常对象){
//异常处理
}finally{
}
格式: try...catch , try ... catch ....finally , try ...finally
public static void main(String[] args) {
System.out.println("======start=====");
try {
System.out.println(10 / 0);
}catch (Exception e) {
System.out.println("异常处理:" + e);
}
System.out.println("======end=====");
}
有个问题,直接打印异常,得到的异常信息是不完整,如果想要获得完整的异常信息,可以使用异常类中提供的 printStackTrace() 方法
public static void main(String[] args) {
System.out.println("======start=====");
try {
System.out.println(10 / 0);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("======end=====");
}
public static void main(String[] args) {
System.out.println("======start=====");
try {
System.out.println(10 / 0);
}catch (Exception e) {
e.printStackTrace();
}finally {
System.out.println("不管是否出现异常,都会执行");
}
System.out.println("======end=====");
}
处理多个异常
public class Demo01 {
public static void main(String[] args) {
System.out.println("======start=====");
try {
int x = Integer.parseInt(args[0]);
int y = Integer.parseInt(args[1]);
System.out.println(x / y);
}catch (Exception e) {
e.printStackTrace();
}finally {
System.out.println("不管是否出现异常,都会执行");
}
System.out.println("======end=====");
}
}
- 程序执行的时候,没有输入 初始化参数
ArrayIndexOutOfBoundsException
- 输入的数据不是数字
java.lang.NumberFormatException
-
输入的被除数 为 0
java.lang.ArithmeticException: / by zero
还有好多好多的异常,举不完,有印象,会英语就行
public static void main(String[] args) {
System.out.println("======start=====");
try {
int x = Integer.parseInt(args[0]);
int y = Integer.parseInt(args[1]);
System.out.println(x / y);
}catch (ArithmeticException e) {
e.printStackTrace();
}catch (NumberFormatException e) {
e.printStackTrace();
}finally {
System.out.println("不管是否出现异常,都会执行");
}
System.out.println("======end=====");
}
异常的处理流程
通过分析发现整个异常处理流程实际操作的还是一个异常的实例化对象,那么这个异常类的实例化对象类型就成为了理解异常处理的核心冠军所在
Throwable 提供两个子类:
- Error:此时程序还未执行出现的错误,开发者无法处理
- Exception:程序中出现的异常,开发者可以处理,真正在开发中需要关注的就是Exception
throws
如果定义了一个方法,实际上应该明确的告诉 使用者,这个方法可能会产生什么异常,那么此时就可以在方法的声明上使用 throws 关键字进行异常类型的标注
public class Test {
public static void main(String[] args) {
try {
System.out.println(MyMath.div(10, 2));
} catch (Exception e) {
e.printStackTrace();
}
}
}
主函数本身也是一个方法,实际上主函数也可以继续向上抛出异常。那么就表示此异常交由JVM负责处理。
public class Test {
public static void main(String[] args) throws Exception {
System.out.println(MyMath.div(10, 2));
}
}
throw 关键字
这个关键字的作用就在于表示手工进行异常的抛出,即此时将手工产生一个异常类的实例化对象,并且进行异常的抛出处理。
public class Demo {
public static void main(String[] args) {
try {//异常对象不再由系统产生,而是手工定义
throw new Exception("我自己抛这玩的");
} catch (Exception e) {
e.printStackTrace();
}
}
}
throw 与throws的区别
- throw : 在代码块中使用,主要手动进行异常对象的抛出
- throws:是在方法定义上使用,表示将此方法可能产生的异常明确告诉给调用出,由调用处进行处理
异常的处理模型
定义一个可以实现 除法 计算的方法
- 在进行数学运算开始与 结束的时候进行信息提示
- 如果在计算的过程中产生了异常,交给调用处理。
public class MyMath {
public static int div(int x , int y) throws Exception{
int temp = 0;
System.out.println("开始运算");
temp = x / y;
try {
temp = x / y;
}catch (Exception e) {
throw e;//向上抛捕获的异常对象
}finally {
System.out.println("结束");
}
return temp;
}
}
public class Test {
public static void main(String[] args) {
try {
System.out.println(MyMath.div(10, 0));
} catch (Exception e) {
e.printStackTrace();
}
}
}
修改
public class MyMath {
public static int div(int x , int y) throws Exception{
int temp = 0;
System.out.println("开始运算");
temp = x / y;
try {
temp = x / y;
}finally {
System.out.println("结束");
}
return temp;
}
}
RuntimeException
public class Demo01 {
public static void main(String[] args) {
int num = Integer.parseInt("123");
System.out.println(num);
}
}
点开 Integer 类的 parseInt()方法 的定义 public static int parseInt(String s) throws NumberFormatException
这个方法上明确的抛出了一个异常,但是在处理的时候并没有强制性要求处理,观察 NumberFormatException 类的继承结构
如果现在所有的程序执行只要使用了 throws 关键字的方法都必须要求 开发者手动处理,那么这个代码的编写就太麻烦了,所以在设计的过程中,考虑到代码编写的方便,所以提供了一个灵活的可选包的异常处理父类 “RuntimeException” , 这个类的异常的子类不需要强制性处理。
RuntimeException 与 Exception的区别
- RuntimeException 是 Exception 的子类
- RuntimeException 标注的异常可以不需要强制性处理,而 Exception 异常必须强制性处理
自定义异常
对于自定义异常有两种方式:
- 继承Exception
public class BombException extends Exception{
public BombException(String msg) {
super(msg);
}
}
public class Food {
public static void eat(int num) throws BombException {
if (num > 10) {
throw new BombException("吃太多了");
}else {
System.out.println("正常吃");
}
}
}
public class Test {
public static void main(String[] args) throws BombException {
Food.eat(11);
}
}
- 继承 RuntimeException
public class BombException extends RuntimeException{
public BombException(String msg) {
super(msg);
}
}
public class Food {
public static void eat(int num) throws BombException {
if (num > 10) {
throw new BombException("吃太多了");
}else {
System.out.println("正常吃");
}
}
}
public class Test {
public static void main(String[] args) {
Food.eat(11);
}
}
Exception : 强制抛出异常
blic static void eat(int num) throws BombException {
if (num > 10) {
throw new BombException(“吃太多了”);
}else {
System.out.println(“正常吃”);
}
}
}
public class Test {
public static void main(String[] args) {
Food.eat(11);
}
}
Exception : 强制抛出异常
RuntimeException :不必强制抛出异常