目录
一、异常概述
在程序中,错误可能产生于程序员没有预料到的各种情况,或者是超出了程序员可控范围的环境因素,如试图打开一个根本不存在的文件等,在 Java中,这种在程序运行时可能出现的一些错误称为异常;
Java语言的异常处理机制优势之一就是可以将异常情况在方法调用中进行传递,通过传递可以将异常情况传递到合适的位置再进行处理, 这种机制类似于现实中发现了火灾,一个人是无 法扑灭大火的,那么可以将这种异常情况传递给119,119 再将这个情况传递给附近的消防队,消防队及时赶到并进行灭火。使用这种处理机制,使得Java语言的异常处理更加灵活,Java语言编写的项目更加稳定。当然,异常处理机制也存在一些弊端,例如,使用异常处理可能会降低程序的执行效率,增加语法复杂度等。
例题代码:
public class Baulk { //创建Baulk
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
int result = 3 / 0; //定义int型变量并赋值
System.out.print(result); //将变量输出
}
}
运行结果:
根据给出的错误提示可知,发生错误的原因是因为在算术表达式“3/0”中,0作为除数出现,系统不再执行下去,提前结束。
二、异常的抛出和捕捉
1.抛出异常
异常抛出后,如果不做任何处理,程序就会被终止;例如,将一个字符串转换为整型,可以通过Integer类的parselt()方法来实现。但如果该字符串不是数字形式,parselnt()方法就会抛出异常,程序将在出现异常的位置终止,不再执行下面的语句;为了保证程序有效的运行,需要对抛出的异常进行相应的处理。
例题代码:
public class Thundering { //创建类
public static void main(String[] args) { //主方法
String str="lili"; //定义字符串
System.out.println(str+"年龄是:"); //输出的提示信息
int age = Integer.parseInt("20L"); //数据类型的转换
System.out.println(age); //输出信息
}
}
运行结果:
因为计算机误把long类型的“20L”认为字符串,而字符串是不能转换为int类型的,所以报错;
将"L"删除,即可运行
运行结果:
2.捕捉异常
异常捕获结构由try、catch和finally 3部分组成
try语句块存放的是可能发生的Java语句;
catch语句块在try语句块之后,用来激发被捕获的异常;
finally语句块是异常处理结果的最后执行部分,无论try语句块中的代码如何退出,都将执行finall语句块,语法如下:
try{
//程序代码块
}
catch(Exception1 e){
//对Exception1的处理
}
catch(Exception2 e){
//对Exception2的处理
}
...
finally{
//程序代码块
}
处理操作中的五个关键词:
throws: 声明本方法中可能会发生某某异常
throw: 抛出某某异常
try, catch, finally: 捕获并处理某某异常
(1).try、catch语句就是用来捕捉和异常处理的;
例题代码:
public class Take {
public static void main(String[] args) {
//数字格式异常
try {//try语句块中包含可能出现异常的程序代码
String str = "lili";//定义字符串变量
System.out.println(str + "年龄是:");//输出的信息
int age = Integer.parseInt("20L");//数据类型转换
System.out.println(age);
}catch(NumberFormatException e){//catch语句块用来获取异常信息
System.out.println("!!出现数字格式异常!!");
System.out.println("请联系管理员进行修复");//输出信息
}
}
}
运行结果:
(2).finally语句块
无论程序是否出现异常,都会执行finally语句,但是在以下四种情况不会执行finally语句块
1.在finally语句块中出现异常
2.在前面的代码块中使用了System.exit()退出程序
3.程序所在线程死亡
4.关闭cpu
三、常见的异常类
四、自定义异常类
在程序中使用自定义异常类,大体可分为以下几个步骤:
1.创建自定义异常类
2.在方法中通过throw关键字抛出异常对象。
3.如果在当前抛出异常的方法中处理异常,可以使用try-catch语句块捕获并处理,否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续惊醒下一步操作。
4.在出现异常的方法的调用者中捕获并处理异常。
例题9.4
public class MyException extends Exception{ //创建自定义异常,继承Exception类
public MyException (String ErrorMessage){ //构造方法
super(ErrorMessage); //父类构造方法
}
]
例题9.5
public class Tran { //创建类
static int avg(int num1,int num2) throws MyException { //定义方法
if(num1 < 0 || num2 < 0) { //判断方法中是否满足指定条件
throw new MyException("不可以使用负数"); //错误信息
} //
if(num1 > 100 || num2 > 100) { //判断方法中参数是否满足指定条件
System.out.println("大于100,午饭计算");
}
return (num1 +num2)/2; //将参数的平均值返回
}
public static void main(String[] args) { //主方法
try { //try语句处理可能出现异常的代码
int result = avg(-32,56); //调用avg()方法
System.out.println(result); //将avg()方法的返回值输出
}catch(MyException e) {
System.out.println(e); //输出异常信息
}
}
}
运行结果如下:
五、在方法中抛出异常
1、使用throws关键字抛出异常:
throws将代码中可能产生的异常交给别人来处理;throws 应用在明法时,用来指定方法可能抛出的异常,多个异常可使用逗号分隔;语法如下:
public void method() throws 异常类型1,异常类型2,...异常类型n{
}
创建方法时,可以使用throws将可能发生的异常抛出,抛出以后该方法就不需要用try-catch来处理,当调用一个含有throws声明异常抛出的方法时,要求必须处理该异常,而处理方式有两种:
(1).使用try-catch捕获并解决异常
(2).在当前方法上继续使用throws声明该异常的抛出
//被调用时
try{
method();
}catch(异常类型 e){
e.printStackTrance();
}
实例代码:
public class Shoot {
static void pop()throws NegativeArraySizeException{
//定义方法并抛出NegativeArraySizeException异常
int [] arr=new int[-3];
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
pop();
}catch(NegativeArraySizeException e) {
System.out.println("pop()方法抛出的异常");
}
}
}
运行结果:
2、使用throw关键字抛出异常
通过throw抛出异常后,如果想在上一级代码中捕获并处理异常,则需要在抛出异常的方法中使用throws关键字在方法的声明中指明要抛出的异常;如果要捕捉throw抛出的异常,则必须使用try-catch语句块。
例题9.7
public class MyExcption extends Exception{ //创建自定义异常类
String message; //定义String类型变量
public MyExcption(String ErrorMessagr) { //父类方法
message = ErrorMessagr;
}
public String getMessage() { //覆盖getMessage()方法
return message;
}
}
例题9.8
public class Captor { //创建类
static int quotient(int x,int y)throws MyException{ //定义方法抛出异常
if(y < 0) { //判断参数是否小于0
throw new MyException("除数不能是负数"); //异常信息
}
return x/y; //返回值
}
public static void main(String[] args) { //主方法
try { //try语句块包含可能发生异常的语句
int result =quotient(3,-1); //调用方法quotient()
}catch(MyException e) { //处理自定义异常
System.out.println(e.getMessage()); //输出异常信息
}catch(ArithmeticException e) { //处理ArithmeticException异常
System.out.println("除数不能为0"); //输出提示信息
}catch(Exception e) { //处理其他异常
System.out.println("程序发生了其他的异常"); //输出提示信息
}
}
}
运行结果:
六、运行时异常
运行时异常都是RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;
当出现RuntimeException的时候,我们可以不处理。当出现这样的异常时,总是由虚拟机接管。比如:我们从来没有人去处理过NullPointerException异常,它就是运行时异常,并且这种异常还是最常见的异常之一。
七、异常的使用原则
异常使用可遵循下面的原则:
(1).不要过度使用异常,虽然通过异常可以增强程序的健壮性,但如果使用过多不必要的异常处理,可能会影响程序的执行效率;
(2).不要使用过于庞大的 try...catch块;在一个try块中放置大量的代码。这种写法看上去“很简单”但是由于try块中的代码过于庞大,业务过于复杂,会造成try块中出现异常的可能性大大增加,从而导致分析异常原因的难度也大大增加;
(3).避免使用catch(Exception);因为如果所有异常都采用相同的处理方式,将导致无法对同异常分情况处理;另外,这种捕获方式可能将程序中的全部错误,异常捕获到,这时如果出现些“关键”异常,可能会被“悄悄地”忽略掉;
(4).不要忽略捕捉到的异常,遇到异常一定要及时处理;
(5).如果父类抛出多个异常,则覆盖方法必须抛出相同的异常或其异常的子类,不能抛出来异常。