1.异常的概念
异常是指在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序.也称为例外.
2.错误的分类
•
通常程序中的错误可分为三种类型
:
1.
编译错误:编译器能够检测到的错误,一般是语法错误。此时不能将源代码
(.java)
编译成可执行的字节码文件
(.class)
。
2.
运行错误:程序运行时产生的错误,例如被
0
除、数组下标越界等等。
3.
逻辑错误:这是机器本身无法检测的,需要程序员对运行结果及程序逻辑进行分析才能发现,逻辑错误可能会导致运行结果错误,有时也可能会导致运行错误。
3.异常处理机制的概念
1.
异常又称为例外,是特殊的运行错误对象。
2.
程序在运行期间可能会遇到一些非预期的或不正常的错误,这些错误将会阻止程序的正常运行。
3.
当发生异常时,系统中需要有一个相应的机制来处理它,确保程序可以继续正常运行,而不会产生死机、死循环或其他对操作系统的损害,从而保证整个程序运行的安全性。这就是异常处理机制。
4.
应用
Java
的异常处理机制,在程序出现异常时,程序员可以捕获该异常,并进行相应的处理。
4.Java中的错误类型
1.
在
Java
中有两种类型的错误:
Exception
类
(
异常
)
和
Error
类
(
错误
)
。
2.
Exception
类是所有异常类的父类,包括了一些由程序本身及环境所产生的错误。应用
Java
的异常处理机制,异常
(Exception)
可以被捕获并进行相应的处理。例如数组下标越界、被
0
除等等。
3.
Error
类则包括了一些较少发生的内部系统错误
。
这些错误都是严重的错误,用户程序无法进行处理,只能通知使用者关闭程序。例如内存不足、虚拟机内部错误等等。
4.
Exception
类和
Error
类都是
Throwable
类的子类。
•
对于具体的异常,不应该使用
Throwable
类,而应该使用
Exception
或
Exception
的子类。
5.Java的预定义异常
1.
ClassNotFoundException
:无法找到指定的类时发生该异常。
2.
FileNotFoundException
:访问一个不存在的文件时发生该异常。
属于IOException
1.
IOException
:通常的
I/O
错误。
2.
ArithmeticException
:
–
如果除数为
0
,则发生该异常。例:
int
i =12 / 0;
3.
NullPointerException
:
–
对象未实例化时访问该对象则发生该异常。
–
例:
int
[] a= null;
a.toString
();
4.
ArrayIndexOutOfBoundsException
:
–
数组下标越界异常。例:
int
[] a= { 1 }; a[1] = 2;
2.3.4属于RuntimeException
5.
NumberFormatException
:
–
数字格式化异常。例:
Integer.parseInt
("
abc
");
6.异常的发生
1.
异常的发生有两种情况:
–
系统自动抛出异常。一般是由于编程错误或者数据错误而导致的异常。
–
显式使用
throw
语句抛出异常。
2.
显式抛出异常的步骤:
–
使用
new
创建异常类的对象,该对象类型是
Exception
或
Exception
的子类。
–
使用
throw
语句抛出异常。
7.异常的捕获和处理
1.
使用
try{}catch{}
块捕获异常
2.
语法:
try {
可能会发生异常的代码
} catch(异常类型异常变量名) {// 捕获例外
异常处理代码 // 处理异常
}
3.
发生的异常类型与
catch
中
异常的类型相同则可以被捕获
4.
发生的异常类型是
catch
中异常的类型的子类也可以被捕获
5.
如果
try
部分的代码没有发生错误,
catch
块的代码不会执行
6.
如果一段代码肯定不会发生异常,则可以不用
try{}catch{}
块
7.
嵌套时内层的
catch
捕捉的异常类型不能外层异常的父类。
8. 多个异常的捕获和处理
1.
可用一组并列的
catch
块处理多个异常的情况
2.
语法:
try {
可能会发生异常的代码
} catch(异常类型1 异常变量名) {
异常处理代码
} catch(异常类型2 异常变量名) {
异常处理代码
}
……
3.
注意点:
–
按从上到下顺序捕获
(
注意排列顺序
)
多个
catch
块中,如果异常类型没有父子关系,则
catch
块的顺序可以随意,如果有父子关系,则子类
catch
块必须写在前面,父类
catch
块写在后面
9.异常处理过程
1.
当遇到关键字“
throw”
时就抛出一个例外
2.
将控制转移到相关的“
catch”
块中处理
3.
如果产生异常的方法没有处理该异常的“
catch”
语句
块,
则继续将该异常往外抛
4.
退出当前方法并转向上一级调用此方法的方法的“
catch”
语句
块
5.
若始终没有“
catch”
块来处理该异常则由运行系统处理
10.非检查型异常和检查型异常
1.
非检查型异常:
–
所有继承自
RuntimeException
的异常称为非检查型异常。
–
编译器对非检查型异常不做编译检查。
2.
检查
型异常:
–
非检查型异常以外的异常称为检查型异常。
–
方法中可能抛出的检查型异常必须在方法定义部分使用
throws
语句进行声明。
–
对于任何方法,如果它调用的方法会抛出一个检查型异常,那么调用者就必须捕获该异常或者也在方法定义部分使用
throws
语句声明会抛出该类型的异常。
–
如果
未捕获该异常也未使用
throws
声明会发生编译错误。
(只有
RunTimeException
才可以不用显示的
throws
出来,即在方法头部写出,其他的异常则必须显示的抛出)
11.Exception类的常用方法
1.
String
getMessage
()
:
返回
异常的详细信息
2.
String
toString
()
:
返回
异常的
描述,包括
类名、
详细信息
3.
void
printStackTrace
()
:
打印出异常发生的路径,以及引起异常的方法调用的序列
12. 自定义异常
1.
除了
使用系统预定义的异常类外,还可以声明自己的异常类。
2.
自定义异常必须继承自
Exception
或
Exception
的子类。
3.
可以在自定义异常类中添加构造方法、成员变量和成员方法。
4.
语法:
class 类名extends异常类名{
// 成员变量、成员方法
}
13.finally
1.
finally
:不论是否有异常发生,
finally
中的代码都要执行
2.
作用:用于非内存的系统资源的释放,如关闭打开的文件、关闭数据库连接等等。
3.
语法:
try {
……
} catch(异常类名e){
……
} finally {
……
}
14.异常处理的嵌套
1.
finally
:不论是否有异常发生,
finally
中的代码都要执行
2.
作用:用于非内存的系统资源的释放,如关闭打开的文件、关闭数据库连接等等。
3.
语法:
try {
……
} catch(异常类名e){
……
} finally {
……
}
练习
1.
设计一个异常类
FlowException
,
该类继承自
Exception
,
getMsg
()
方法返回错误信息。
(
格式:
id
的值:
msg
的值
)
2.
定义一个异常测试类
ExceptionTest
–
定义一个方法
test
,该方法接收
2
个整型的参数
num1
和
num2
,如果
num1
-
num
2<=
0
,
则抛出异常FlowException,
错误信息为“404
:
Under
Value
Err”
;
如果
num1- num2 >= 1000
,
则抛
出异常
FlowException
,
错误信息为”
405
:
OverValue Err”
在
main
方法中通过键盘输入
2
个数,测试方法
test
并显示错误信息。
代码
package com.hisoft.java.exceptiondemo;
import java.util.Scanner;
/**
*
* @author MR.Ren
* @data 2018年1月30日下午5:22:26
* @className FlowException.java
*/
public class FlowException extends Exception {
private static final long serialVersionUID = 1L;
private int id;// 定义成员变量id
private String msg;// 定义成员变量msg
public FlowException(int id, String msg) {// 有参构造方法并初始化
this.id = id;
this.msg = msg;
}
// getMsg()方法返回错误信息
public String getMsg() {
return id + ":" + msg;
}
}
// 异常测试类
class ExceptionTest {
public static int test(int num1, int num2) throws FlowException {
if (num1 - num2 <= 0) {
throw new FlowException(404, "Under Value Err");// 抛出异常信息
}
if (num1 - num2 >= 1000) {
throw new FlowException(405, "Over Value Err");// 抛出异常信息
}
return num1 - num2;
}
public static void main(String[] args) {
// 使用try--catch处理异常
try {
Scanner sc = new Scanner(System.in);
System.out.print("num1 = ");
int num1 = sc.nextInt();
System.out.print("num2 = ");
int num2 = sc.nextInt();
test(num1, num2);
sc.close();
} catch (FlowException e) {
System.out.println(e.getMsg());
e.printStackTrace();
}
}
}