7/31异常处理
概述:
1、异常就是在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序。
2、Java编程语言使用异常处理机制为程序提供了错误处理的能力。
3、Exception和Error都是Throwable的子类:
Error:Error 类的异常为内部错误,正常情况下不期望用户的程序捕获它们 。
Exception:异常层级结构的根类。
千万不要拿异常当错误处理!!!
4、两种类型:
CheckedException:Checked Exception是会显示提示错误的异常;
UncheckedException:而Unchecked Exception是不会提示错误信息,但运行时会打印异常信息的异常。
如下图:
异常五个关键字:
try、catch、finally、throw、throws
详解如下:
异常处理块的一般形式:
try-catch语句的三种情况
1、情况一:程序不发生异常,try语句执行完成后,跳过catch块,执行try-catch后面的语句。
2、情况二:程序发生异常,产生了异常对象,将异常对象与后面的catch块进行匹配,找到匹配的catch块,进入catch块,执行catch语句,完成后,执行try-catch块后面的语句。
3、情况三:程序发生异常,产生异常对象,没有找到匹配的catch块,程序运行中断。
三种情况对于同一个程序的不同结果:
import java.util.Scanner;
public class HelloAccp {
public static void main(String[] args) {
System.out.print("请输入1至3之间的数字:");
Scanner s = new Scanner(System.in);
try{
int courseCode = s.nextInt();
switch(courseCode){
case 1:
System.out.println("C#编程");
break;
case 2:
System.out.println("JAVA编程");
break;
case 3:
System.out.println("SQL基础");
}
}catch(Exception se){
System.out.println("请输入数字!");
se.printStackTrace();
}
System.out.println("欢迎使用!");
}
}
第一种情况运行结果:
请输入1至3之间的数字:3
SQL基础
欢迎使用!
第二种情况运行结果:
找到匹配的catch块,异常处理后,后面的语句继续执行。
第三种情况运行结果:(运行前先将catch语句中的Exception改成NullPointerException,为了找不到匹配的catch块)
没有找到匹配的catch语句,程序中断,后面的语句不再执行。
try-catch-finally:(异常处理的一般情况)
try必须有,catch或finally至少有一个!且finally有的话,最多只能有一个;而catch块可以有多个。
无论try中的异常是否找到匹配的catch语句,finally块都会执行。
多重的catch语句:
一段代码中,一个try块可以有多个catch块;当引发异常时,会按顺序来依次查看每个 catch 语句,并执行第一个与异常类型匹配的catch语句;
执行其中的一条 catch 语句之后,其后的 catch 语句将被忽略 。
如下面代码:
public class AccpException4 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
try{
System.out.print(“请输入S1的总学时:");
int totalTime = in.nextInt(); //总学时
System.out.print(“请输入S1的课程数目:");
int totalCourse = in.nextInt(); //课程数目
System.out.println(“S1各课程的平均学时为:"+ totalTime / totalCourse);
} catch (InputMismatchException e1) {
System.out.println("输入不为数字!");
} catch (ArithmeticException e2) {
System.out.println("课程数目不能为零!");
} catch (Exception e) {
System.out.println("发生错误:"+e.getMessage());
}
}
}
对上述代码进行三种情况的测试:
如下面测试结果:
**输入正常的情况:**
请输入S1的总学时:
260
请输入S1的课程数目:
40
S1的平均学时为:6
**输入的学时不是数字:**
请输入S1的总学时:
asd
输入不为数字!
**输入的课程数为零的情况:**
请输入S1的总学时:
1200
请输入S1的课程数目:
0
课程数目不能为0!
try-catch、try-catch-finally、throws的区别:
1、try-catch语句:如果try程序块里面捕获到的异常,在catch块中可以找到相匹配的catch语句,则处理异常后,try-catch块后面的语句还会继续执行;但如果没有找到相匹配的catch块,则程序将就此中断,后面的语句不会再执行。
如下列程序:
import java.util.Scanner;
public class HelloAccp {
public static void main(String[] args) {
System.out.print("请输入1至3之间的数字:");
Scanner s = new Scanner(System.in);
try{
int courseCode = s.nextInt();
switch(courseCode){
case 1:
System.out.println("C#编程");
break;
case 2:
System.out.println("JAVA编程");
break;
case 3:
System.out.println("SQL基础");
}
}catch(Exception se){
System.out.println("请输入数字!");
se.printStackTrace();
}
System.out.println("欢迎使用!");
}
}
运行结果:
请输入1至3之间的数字:3
SQL基础
欢迎使用!
输入正常,没有捕获到异常,程序正常结束。若抛出异常,可见上述try-catch的第二种情况可以找到匹配的catch块的详解。
2、而在try-catch-finally语句中,无论有多少个catch语句,无论是否找到匹配的catch,finally语句都会执行。
示例代码如下:
public class HelloAccp {
public static void main(String[] args) {
System.out.print("请输入1至3之间的数字:");
Scanner s = new Scanner(System.in);
try{
int courseCode = s.nextInt();
switch(courseCode){
case 1:
System.out.println("C#编程");
break;
case 2:
System.out.println("JAVA编程");
break;
case 3:
System.out.println("SQL基础");
}
}catch(NullPointerException se){//异常类型不匹配!
System.out.println("请输入数字!");
se.printStackTrace();
}finally{
//无论是否匹配都会执行
System.out.println("欢迎使用!");
}
}
}
运行结果:
请输入1至3之间的数字:
qwe
欢迎使用!
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
at 实训731.HelloAccp.main(HelloAccp.java:10)
3、如果在方法中throws声明异常,在异常发生后,处理异常,后面的语句不会再执行。
代码示例:
public class MyException extends Exception{
private int i;
MyException(int a){
i = a;
}
public String toString(){
return i+"大于10啦!";
}
}
public class MyExceptionTest {
static void go(int a) throws MyException{
System.out.println("a="+a);
if(a>10){
throw new MyException(a);
}
System.out.println("正常结束!");
//在throws里面,检测到异常后,后面的语句将不再被执行
}
public static void main(String[] args) {
try{
go(1);
go(15);//后面的正常结束将不再被输出
}catch(MyException e){
System.out.println("捕获异常:"+e);
}
}
}
运行结果:
a=1
正常结束!
a=15
捕获异常:15大于10啦!
在本例中,go(15);在执行的过程中抛出异常,后面的正常结束将不会再输出。
Java常见异常类:
用户自定义异常
在另一个方法中捕获并处理异常
在一个方法中使用throw抛出异常
为该异常类添加构造方法
创建一个类继承 Exception 或其子类
随堂练习:
1.编写如下异常类:
空异常(NullException ,年龄低异常(LowAgeException),年龄高异常(HeightAgeException),
工资低异常(LowSalaryException),工资高异常(HighSalaryException),身份证非法异常(IdCardException)
2.编写一个员工类,
(1) 有属性:
编号,姓名,年龄,工资,身份证号码,员工人数(10),员工工资总额(10000)
(2) 有构造器:
构造器1:设置编号,年龄,姓名;如果年龄小于18,抛出年龄低异常;如果年龄大于60
抛出年龄高异常,如果姓名为null或为空字符串,抛出空异常。
构造器2:设置工资,设置身份证号码;如果工资低于600,抛出工资低异常。
如果身份证不是18位,抛出身份证非法异常。
(3) 有方法
增加工资 addSalary(double addSalary),抛出工资高异常,当增加后的工资大于员工工资总额时,抛出此异常。
减少工资 minusSalary(double minusSalary), 抛出工资低异常,当减少后的工资低于政府最低工资时,抛出工资低异常。
显示员工工资总额方法:showTotalSalary(),抛出空异常,当工资总额为0时,抛出此异常。
显示员工人数:voidshowTotalEmployee(),抛出空异常。当员工人数为0时,抛出此异常
3.编写main主测试类
分别生成3个员工,测试构造方法的异常抛出。
每个员工分别增加,减少工资,测试方法的异常。
显示员工的人数和工资总额。
public class Employee {
private int id;
private String name;
private int age;
private double salary;
private String id_card;
private int totalEmployee = 10;
private double totalSalary = 1000;
public Employee(int id1,String name1,int age1) throws Exception{
if(age1<18){
throw new LowAgeException("年龄太小!");
}else if(age1>60){
throw new HighAgeException("年龄太大!");
}
if(name1==null||name1==""){
throw new NullException("姓名为空!");
}
}
public double getSalary() {
return salary;
}
public Employee(double salary1,String id_card1) throws Exception{
this.salary = salary1;
if(salary<600){
throw new LowSalaryException("工资太低!");
}
if(id_card1.length()!=18){
throw new IdCardException("身份证号不是18为!");
}
}
public void addSalary(double addsalary) throws Exception{
double salary_add = salary + addsalary;
System.out.println("增加后的工资为:"+salary_add);
if(salary_add>totalSalary){
throw new HighSalaryException("增加后的工资太高!");
}
}
public void minusSalary(double minusSalary) throws Exception{
salary = salary - minusSalary;
if(salary<600){
throw new LowSalaryException("减少后的工资低于政府工资!");
}
}
public void showTotalSalary(double sum) throws NullException{
//double totalSalary = 0;
System.out.println("工资总额为:"+sum);
if(sum == 0){
throw new NullException("工资总额为零!");
}
}
public void showTotalEmployee(int num) throws NullException{
System.out.println("员工人数为:"+num);
if(num == 0){
throw new NullException("员工人数为零!");
}
}
}
Test测试类:
public class Test {
public static void main(String[] args){
double sum = 0;
int num=0;
try {
//测试年龄低异常
Employee employee = new Employee(12,"tom",15);
sum = sum + employee.getSalary();
num = num + 1;
//测试低工资异常
employee = new Employee(200,"123456789012345678");
sum = sum + employee.getSalary();
num = num + 1;
//测试年龄高异常
employee = new Employee(12,"tom",65);
sum = sum + employee.getSalary();
num = num + 1;
//测试名字为空异常
employee = new Employee(12,"",24);
sum = sum + employee.getSalary();
num = num + 1;
//测试身份证不够18位异常
Employee employee1 = new Employee(700,"1234567890");
sum = sum + employee1.getSalary();
num = num + 1;
//增加工资后大于1000的异常
employee = new Employee(700,"123456789012345678");
sum = sum + employee.getSalary();
num = num + 1;
employee.addSalary(500);
//减少工资后小于600
employee = new Employee(1000,"123456789012345678");
sum = sum + employee.getSalary();
num = num + 1;
employee.minusSalary(500);
//正常
employee = new Employee(1200,"123456789012345678");
sum = sum + employee.getSalary();
num = num + 1;
//正常
employee = new Employee(1500,"123456789012345678");
sum = sum + employee.getSalary();
num = num + 1;
employee.showTotalSalary(sum);
employee.showTotalEmployee(num);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
六个异常类:
//年龄高异常
public class HighAgeException extends Exception{
public HighAgeException(String message){
super(message);
}
}
//工资高异常
public class HighSalaryException extends Exception{
public HighSalaryException(String message){
super(message);
}
}
//身份证异常
public class IdCardException extends Exception{
public IdCardException(String message){
super(message);
}
}
//年龄低异常
public class LowAgeException extends Exception{
public LowAgeException(String message){
super(message);
}
}
//工资低异常
public class LowSalaryException extends Exception{
public LowSalaryException(String message){
super(message);
}
}
//空异常
public class NullException extends Exception{
public NullException(String message){
super(message);
}
}
运行结果:
对上述Test测试类,将每个测试内容放到一个try-catch语句中,方可得到结果。