定义:在java语言中,异常是指程序在运行期间发生的事件,它是导致程序中断运行的正常指令流。
任何有关于程序潜在会出错的程序都会被编译器显示成为异常。
异常分类
Throwable类
位于异常类层次结构的顶端,它是Java中所有错误和异常的父类
Error类
与虚拟机有关,如系统崩溃、虚拟机错误、动态链接失败,不可恢复的错误
Exception类
该类型的异常在程序中发生后可以进行捕获处理,处理后程序正常运行,从而保证程序的稳定性和健壮性。
Java程序开发中的异常处理,主要是针对Exception类及其子类进行的。
常见时运行时异常RuntimeException
ArithmeticException | 算术异常 |
ClassCastException | 对象转换异常 |
NegativeException | 数组长度为负值异常 |
Java异常处理的运行机制
当程序运行出现意外情形时,系统会自动生成一个Exceptin类型的子类对象来通知程序,从而实现业务功能的代码与错误处理代码分离,使程序具有更好的可读性。
Java的异常处理机制提供了两种方式来处理异常,一种是使用“try-catch"语句处理异常,另一种是在方法时使用throws关键字将异常抛出。
语法:
try{
//可能出现异常的语句
}catch(异常类型1 异常对象1){
//异常吹了代码
}
演示try-catch捕获异常
public class Exception {
public static void main(String[] args) {
try {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个整数:");
int num = scanner.nextInt();
System.out.println("您输入的数字是:" + num);
} catch (InputMismatchException e) {
System.err.println("输入不匹配异常:程序只能接受整数");
}
}
}
一个try块可以有多个catch块,捕获不同的异常,但只能先处理一个,一般先处理小异常,再处理大异常,否则将出现编译错误。
System.err.println是什么
err是运行期异常和错误反馈的输出流的方向
System.err.println只能在屏幕上实现打印,即使你重定向了也一样
用err打印出的字符串,再eclipse的console会显示红色
使用finally回收资源
语法:
try{
//可能出现异常的语句
}catch(异常类型1 异常对象1){
//异常处理代码
}finally{
//资源回收代码
}
finally块保证回收在try块当中打开的物理资源,如数据库连接、网络连接或磁盘文件等。
无论try语句块中的代码是否出现异常,try语句块对应的任意一个catch语句块是否被执行,甚至在try或catch语句块中执行了return语句,finally块总会被执行。
无论是try语句块还是catch语句块中使用return语句,都要先执行完finally语句块后,再返回当前方法。
try语句不能独立存在,其后至少要有一个catch语句块或finally语句块。
finally语句块不是必须存在的,可以根据需求是否添加。
throws与throw
java程序不允许出错,若有错就得将这些异常抛出交给异常处理机制处理
throws抛出所有的异常信息,被应用在声明方法时,系统自动将异常抛给上级方法
throw指程序运行中抛出的一个具体的异常Exception,抛出的Exception需要用户来捕获处理,在方法内部使用
实例:在读取文件方法声明时使用Throws抛出可能异常
public class Read {
public static void readFile() throws ClassNotFoundException, FileNotFoundException{
Class.forName("Demo.Read");
FileInputStream inputStream = new FileInputStream("c://file.txt");
}
public static void main(String[]args){
try{
Read.readFile();
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (ClassNotFoundException e){
e.printStackTrace();
}
}
}
在实际的企业开发项目当中,系统是否要抛出异常,可能需要根据数据应用的业务需求来决定,如果程序中的数据处理与指定的业务需求不符合,便算作异常,这种与业务需求不符产生的异常需要要开发人员决定抛出,throw语句抛出的不是一个异常类,而是一个异常实例,且每次只能抛出一个异常实例。
使用throw抛出异常保证员工年龄合乎企业用人规则
public class UserInfo {
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) throws Exception {
if(age<18||age>60){
throw new Exception("員工年齡應該在18至60歲之間");
}
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public UserInfo(String name, int age) {
this.name = name;
this.age = age;
}
public UserInfo(){
}
public static void main(String[] args){
UserInfo userInfo = new UserInfo();
userInfo.setName("俞敏洪");
try{
userInfo.setAge(10);
}catch (Exception e){
e.printStackTrace();
}
}
}
只有设置一个无参数的构造函数才可以不需初始化原有的私有属性
自定义异常
自定义异常类需要继承自Exception类
实例:创建自定义异常类
public class AuctionException extends Exception{
public AuctionException(){
}
public AuctionException(String message){
super(message);
}
}
自定义异常处理的两个特点
1.异常处理的复杂性
异常不能由当前方法处理完毕,异常由当前方法处理一部分,另一部分交由当前方法的调用者进行处理,此时需在当前方法中抛出异常
2.多个方法相互协作处理异常
实例:使用自定义异常处理拍卖过程中的错误操作
public class AuctionTest {
private double initPrice = 30;
public void bird(String bidPrice) throws AuctionException{
double d =0;
try{
d=Double.parseDouble(bidPrice);
}catch (Exception e){
e.printStackTrace();
throw new AuctionException("輸入的競拍價格必須為小樹格式");
}
if(initPrice>d){
throw new AuctionException("競拍價格低於起拍價格,不許競拍");
}
}
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("請輸入商品的競拍價格");
AuctionTest auctionTest = new AuctionTest();
try{
auctionTest.bird(input.next());
}catch (AuctionException e){
System.out.println(e.getMessage());
}
}
}