传统处理异常的方式
public static void main(String[] args) {
System.out.println("请输入一个被除数:");
Scanner sc = new Scanner(System.in);
if(sc.hasNextInt()) {
int num1 = sc.nextInt();
System.out.println("请输入一个除数:");
if(sc.hasNextInt()) {
int num2 = sc.nextInt();
if(0 == num2) {
System.out.println("除数不能为0!");
}else {
int r = num1 / num2;
System.out.println("r = " + r);
}
}else {
System.out.println("除数输入不合法!");
}
}else {
System.out.println("被除数输入不合法!");
}
}
细心的你可以发现其中的缺点:其中的业务逻辑(除法算术)和处理异常的判断逻辑耦合在一起。
代码冗余(这是最致命的)
什么是异常?异常是指在程序的运行过程中所发生的不正常的事件。它会中断正在运行的程序......
幸好,Java编程语言使用异常处理机制为程序提供异常处理的能力,异常处理机制完成后,程序可以继续执行。
异常处理机制
1.try-catchtry{}代码块用于执行可能存在异常的代码,catch{}代码块用于捕获并处理异常。
正常发生的情况:
异常发生的情况:
切记:在异常捕获过程中需要进行异常类型匹配。
异常不匹配的情况:
public class Test01 {
public static void main(String[] args) {
System.out.println("请输入一个被除数:");
Scanner sc = new Scanner(System.in);
try {
int num1 = sc.nextInt();
System.out.println("请输入一个除数:");
int num2 = sc.nextInt();
int r = num1 / num2;
System.out.println("r = " + r);
}catch (InputMismatchException e) {
System.out.println(e.toString());
}
System.out.println("程序执行结束...");
}
}
异常的常见方法:printStackTrace()输出异常的堆栈信息
getMessage()获取异常的描述。
toString()返回异常的类型的异常描述。
2.try-catch-finallytry{}代码块用于执行可能存在异常的代码,catch{}代码块用于捕获并处理异常。
finally{}代码块用于回收资源(关闭文件、关闭数据库、关闭管道)的代码。finally代码块不管是否出现异常,都必须执行。
public class Test01 {
public static void main(String[] args) {
System.out.println("请输入一个被除数:");
Scanner sc = new Scanner(System.in);
try {
int num1 = sc.nextInt();
System.out.println("请输入一个除数:");
int num2 = sc.nextInt();
int r = num1 / num2;
System.out.println("r = " + r);
}catch (Exception e) {
System.out.println(e.toString());
}finally {
System.out.println("finally");
}
System.out.println("程序执行结束...");
}
}finally唯一不执行的情况:System.exit(0) jvm正常退出。
存在return时
package com.kal4;
public class Test02 {
public static int div() {
int a = 10;
int b = 2;
try {
int r = a / b;
return r;
} catch (Exception e) {
System.out.println("异常发生");
return 0;
}finally {
System.out.println("finally");
}
}
public static void main(String[] args) {
int r = div();
System.out.println("r = " + r );
}
}
多重catch
package com.kal4;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Test03 {
public static void main(String[] args) {
System.out.println("请输入一个被除数:");
Scanner sc = new Scanner(System.in);
try {
int num1 = sc.nextInt();
System.out.println("请输入一个除数:");
int num2 = sc.nextInt();
int r = num1 / num2;
System.out.println("r = " + r);
}catch (InputMismatchException e) {
System.out.println("用户输入不匹配异常");
}catch(ArithmeticException e) {
System.out.println("除数为0异常");
}catch(Exception e) {
System.out.println("发生异常");
}finally {
System.out.println("finally");
}
System.out.println("程序执行结束...");
}
}
多重catch书写原则异常子类先匹配
异常父类后匹配,用于默认匹配
异常分类
Throwable 类是 Java 语言中所有错误或异常的父类。Throwable有两个子类Error和Exception。
Error(错误): 仅靠程序本身无法恢复的严重错误。例如:jvm奔溃、jvm内存耗尽。
Exception:靠程序本身通过异常处理机制能处理的非正常情况。
异常分为两类:运行时异常:运行时异常,不要求程序必须做出处理。RuntimeException是所有运行时异常的父类
检测时异常:程序必须处理该类异常。CheckedException表示检查时异常,但java不存在该类。
public class Test01 {
public static void main(String[] args) {
// 检查时异常SimpleDateFormat df = new SimpleDateFormat();
try {
df.parse("2019");
} catch (ParseException e) {
e.printStackTrace();
}
}
}
常见的运行时异常:
InputMismatchException:控制台输入不匹配异常
ArithmeticException:算术计算异常。例如:除数为0
ArrayIndexOutOfBoundsException:数组下标越界
NullPointerException:空指针异常
IllegalArgumentException:方法接收到非法参数
ClassCastException:强制类型转换异常
NumberFormatException:数组格式化异常。如把"abc"转换成数字
NoSuchElementException: 表明枚举中没有更多的元素
ConcurrentModificationException:并发操作异常
常见的检查时异常
ClassNotFoundException:无法找到类异常
SQLException:数据库操作异常。
FileNotFoundException:文件未被发现
IOException:IO异常
ParseException:解析异常
TimeoutException:超时异常
InterruptedException:中断异常。
声明异常
throws:当开发者在定义方法时,事先知道方法在调用时会出现异常。但不知道该如何处理,此时可以在该方法上声明异常,表示该方法在调用过程中会出现异,请调用者自行处理。
public class Test01 {
public static int div(int a,int b) throws ArithmeticException{
int r = a / b;
return r;
}
public static void main(String[] args) {
int m = 10;
int n = 0;
int r = 0;
try {
r = div(m, n);
} catch (ArithmeticException e) {
System.out.println("除数不能为0");
}
System.out.println(r);
}
}
声明异常和重载的关系
其实它们没有任何关系......
声明异常和重写的关系
这个它们有关系......如果父类声明了异常(检查时或运行时),子类可以完全遵循父类异常,亦可以不声明异常。
public class Parent {
public void showInfo() throws Exception{
System.out.println("parnent:showInfo");
}
}
public class Sub extends Parent{
public void showInfo() [throws Exception]{
System.out.println("sub:showInfo");
}
}
2.如果父类完全没有声明异常,子类可以完全遵循父类异常,亦可以声明RuntimeException但不能声明Exception
public class Parent {
public void showInfo() {
System.out.println("parnent:showInfo");
}
}
public class Sub extends Parent{
public void showInfo() throws RuntimeException{
System.out.println("sub:showInfo");
}
}
3.如果父类声明了运行时异常,子类可以完全遵循父类异常,亦可以不声明异常。
public class Parent {
public void showInfo() throws RuntimeException{
System.out.println("parnent:showInfo");
}
}
public class Sub extends Parent{
public void showInfo() [throws RuntimeException]{
System.out.println("sub:showInfo");
}
}
好了,大饼我今天就分享到这吧,我们下期见~