概念:程序在运行过程中出现的特殊(不正常)情况。
异常处理的必要性:任何程序都可能存在大量的未知问题、错误;
如果不对这些问题进行正确处理,则可能导致程序的中断,造成不必要的损失。
Throwable:可抛出的,一切错误或异常的父类,位于java.lang包中。
Error: JVM、硬件、执行逻辑错误,不能手动处理。
Exception:程序在运行和配置中产生的一般问题,可处理。
类型 | 说明 |
---|---|
NullPointerException | 空指针异常 |
ArrayIndexOutOfBoundsException | 数组越界异常 |
ClassCastException | 类型转换异常 |
NumberFormatException | 数字格式化异常 |
ArithmeticException | 算术异常 |
当程序在运行时遇到不符合规范的代码或结果时,会产生异常。
出现异常相当于遇到 return 语句,导致程序因异常而终止。
异常的传递:按照方法的调用链反向传递,如始终没有处理异常,最终会由JVM进行默认异常处理(打印堆栈跟踪信息)并中断程序。
eg:
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:864)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
at StageOne.day16.Exception.Test.main(Test.java:17)
关键字 | 说明 |
---|---|
try | 可能出现异常的代码 |
catch | 捕获异常 |
finally | 异常最终处理,释放资源 |
throw | 抛出异常 |
throws | 声明异常 |
三种情况:
语法:
try {
//可能出现异常的代码
} catch(Exception e) {
//异常处理的相关代码,如:getMessage()、printStackTrace()
}
eg:
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int r = 0;
try {
System.out.println("请输入第一个数: ");
int i = input.nextInt();
System.out.println("请输入第二个数: ");
int i1 = input.nextInt();
r = i/i1;
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("结果是: "+r);
}
}
语法:
try {
//可能出现异常的代码
} catch(Exception e) {
//异常处理的相关代码,如:getMessage()、printStackTrace()
}finally{
//是否发生异常都会执行,可以释放资源等...
}
注:
eg:
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int r = 0;
try {
System.out.println("请输入第一个数: ");
int i = input.nextInt();
System.out.println("请输入第二个数: ");
int i1 = input.nextInt();
r = i/i1;
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("最总处理, 释放资源");
}
System.out.println("结果是:"+r);
}
}
语法:
try{
//可能出现异常的代码
}catch(异常类型1){
//满足异常类型1执行的相关代码
}catch(异常类型2){
//满足异常类型2执行的相关代码
}catch(异常类型3){
//满足异常类型3执行的相关代码
}
注:
eg:
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int r = 0;
try {
System.out.println("请输入第一个数: ");
int i = input.nextInt();
System.out.println("请输入第二个数: ");
int i1 = input.nextInt();
r = i/i1;
} catch (ArithmeticException e) {
System.out.println("算术异常");
} catch (InputMismatchException e) {
System.out.println("输入不匹配异常");
} catch (Exception e) {
System.out.println("未知异常");
}
System.out.println("结果是: "+r);
}
}
语法:
try{
//可能出现异常的代码
}catch(异常类型1){
//满足异常类型1执行的相关代码
}catch(异常类型2){
//满足异常类型2执行的相关代码
}finally{
//是否发生异常都会执行,可以释放资源等...
}
eg:
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int r = 0;
try {
System.out.println("请输入第一个数: ");
int i = input.nextInt();
System.out.println("请输入第二个数: ");
int i1 = input.nextInt();
r = i/i1;
} catch (ArithmeticException | InputMismatchException e) {
System.out.println("算术异常或输入不匹配异常");
} catch (Exception e) {
System.out.println("未知异常");
} finally {
System.out.println("最终处理,释放资源");
}
System.out.println("结果是: "+r);
}
}
try…finally…不能捕获异常,仅仅用来当发生异常时,用来释放资源。
一般用在底层代码,只释放资源不做异常处理,把异常向上抛出。
语法:
try{
//可能出现异常的代码
}finally{
//是否发生异常都会执行,可以释放资源等...
}
eg:
public class Test01 {
public static void main(String[] args) {
try {
divide();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("程序结束了...");
}
public static void divide() {
Scanner input = new Scanner(System.in);
int r = 0;
try {
System.out.println("请输入第一个数: ");
int i = input.nextInt();
System.out.println("请输入第二个数: ");
int i1 = input.nextInt();
r = i/i1;
} finally {
System.out.println("最终处理,释放资源");
}
System.out.println("结果是: "+r);
}
}
? 答: 语法上都可以, 但不推荐在finally中写, 否者会输出错误的数据
? 答: 会执行
以下代码返回多少?并说明执行过程。
eg:
public class Test02 {
public static void main(String[] args) {
System.out.println(getNum());
}
public static int getNum() {
int num = 10;
try {
return num++;
} catch (Exception e) {
return num++;
} finally {
num++;
}
}
}
res: 10
public class Test02 {
public static void main(String[] args) {
System.out.println(getNum());
}
public static int getNum() {
int num = 10;
try {
return num++;
} catch (Exception e) {
return num++;
} finally {
return num++;
}
}
}
res: 11
如果在一个方法体中抛出了异常,如何通知调用者?
throws关键字:声明异常,通知调用者此方法有异常。
使用原则:底层代码向上声明或者抛出异常,最上层一定要处理异常,否则程序中断。
注意事项:
eg:
public class Test01 {
public static void main(String[] args) {
try {
divide();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("程序结束了...");
}
//throws:声明异常,告诉调用者有异常
public static void divide() throws Exception {
Scanner input = new Scanner(System.in);
int r = 0;
System.out.println("请输入第一个数: ");
int i = input.nextInt();
System.out.println("请输入第二个数: ");
int i1 = input.nextInt();
r = i / i1;
System.out.println("结果是"+r);
}
}
除了系统自动抛出异常外,有些问题需要程序员自行抛出异常。
throw关键字:抛出异常
语法: throw 异常对象;
eg:
在setAge(int age)中对年龄进行判断,如果年龄介于1到100直接赋值,否则抛出异常。
在setGender(String gender)中对性别进行判断,如果性别是男或女直接赋值,否则抛出异常
在测试类中创建对象并调用setAge(int age)方法,使用try...catch捕获并处理异常。
Student:
public class Student {
private int age;
private String gender;
public Student(int age, String gender) throws Exception {
this.setAge(age);
this.setGender(gender);
}
public int getAge() {
return age;
}
public void setAge(int age) throws Exception{
if (age<1 || age>100) {
throw new Exception("异常年龄输入");
} else {
this.age = age;
}
}
public String getGender() {
return gender;
}
public void setGender(String gender) throws Exception {
if (gender.equals("男")||gender.equals("女")) {
this.gender = gender;
} else {
throw new Exception("异常性别输入");
}
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
TestStudent:
public class TestStudent {
public static void main(String[] args) {
Student stu = null;
try {
stu = new Student(120, "男");
} catch (Exception e) {
System.out.println("数据异常, 请重新输入...");
}
System.out.println(stu);
}
}
概念:需继承Exception或Exception的子类,代表特定问题。
经验:异常类型名称望文生义,可在发生特定问题时抛出对应的异常。
eg:
public class AgeException extends RuntimeException{
public AgeException() {
}
public AgeException(String message) {
super(message);
}
}
public class GenderException extends RuntimeException{
public GenderException() {
}
public GenderException(String message) {
super(message);
}
}
规则: