定义:什么是异常?
异常就是在程序的运行过程中所发生的不正常事件,如所需的文件找不到、网络连接不通或中断、算数运算出错(如被零除)、数组下标越界、装载了一个不存在的类、对null对象操作、类型转换异常等。异常会中断正在运行的程序。
了解:什么是异常处理?
异常处理机制就像我们对平时可能遇到的意外情况,预先想好了一些处理的办法。也就是说,在程序执行代码的时候,万一发生了异常,程序会按照预定的处理办法对异常进行处理,异常处理完毕之后,程序继续运行。
Java的异常处理是通过5个关键字来实现的:try、catch、finally、throw、throws。
分类讲解:
try-catch块
//示例1
import java.util.Scanner;
public class Test1{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.print("请输入被除数:");
try{
int number1 = input.nextInt();
System.out.print("请输入除数:");
int number2 = input.nextInt();
System.out.println(String.format("%d / %d = %d",number1,number2,number1/number2));
System.out.println("感谢使用本程序!");
}catch(Exception e){
System.out.println("出现错误:被除数和除数必须是整数,"+"除数不能为零。");
e.printStackTrace();
}
}
}
try-catch快的流程比较简单,首先是执行try块里面的程序代码,1、如果没有错误,执行完毕之后正常结束程序,catch块中的代码忽略;2、如果出现异常,try块当中其余的代码会停止执行,如果产生的异常与catch块中声明的异常相同,catch会捕获到相应的异常,并执行catch块中相应的异常;3、如果try块中的代码执行中出现异常,而抛出的异常在catch块中没有声明,那么程序也会立刻退出。
try-catch块-finally
在try-catch块中添加了finally块之后,那么在finally块中的语句无论在任何情况下都会输出!即使在try块和catch块中存在return语句,finally块中的语句也会被执行。发生异常时的执行顺序:执行try块或catch块中return之前的语句,执行finally块中的语句,执行try块或catch块中的return语句退出。
//示例-测试try块和catch块中return语句的执行
public class test{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.print("请输入被除数:");
try{
int a = input.nextInt();
System.out.print("请输入除数:");
int b = input.nextInt();
System.out.pirnt("%d / %d = %d",a,b,a/b);
return;//finally语句块仍旧会被执行
}catch(Exception e){
System.err.println("出现错误:被除数和除数必须是整数,除数不能为零");
return;//finally语句块仍旧会被执行
}finally{
System.out.print("感谢使用本程序!");
}
}
}
OutPut:
请输入被除数:200
请输入除数:0
出现错误:被除数和除数必须是整数,除数不能为零
感谢使用本程序!
请注意:finally唯一不被执行的情况是在异常处理代码中执行System.exit(1),因为这将退出Java虚拟机,仅此一种特殊情况!!其余任何情况下都会执行finally块!!
多重catch块
在程序的程序过程中,会遇到各种异常,异常也分为了许多的种类,因为在异常的捕获时,也会根据不同的异常进行捕获以此加以区分,能够更好的找出异常原因。这时,一个catch块就不够用了,因为一个catch块只能捕获一种异常,而多重catch块便能很好的解决这个问题。
//示例-多重catch块
public class test{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.print("请输入被除数:");
try{
int a = input.nextInt();
System.out.print("请输入除数:");
int b = input.nextInt();
System.out.pirnt("%d / %d = %d",a,b,a/b);
}catch(InputMismatchException e){
System.err.println(被除数和除数必须是整数");
}catch(ArithmeticException e){
System.err.println("除数不能为零");
}catch(Exception e){
System.err.println("出现错误:被除数和除数必须是整数,除数不能为零");
}finally{
System.out.print("感谢使用本程序!");
}
}
}
在多重catch块中,每个catch块中都定义了不同的异常类型,系统会根据不同的异常而执行的catch块,这里需要注意的是,catch块中的异常的排列顺序是从子类到父类,通常Exception类在最后一个catch块。
声明异常——throws关键字
如果在一个方法体中抛出了异常,我们就希望调用者能够即时地捕获异常,那么如何通知调用者呢?Java语言中通过关键字throws声明某个方法可能抛出的各种异常。throws可以同时声明多个异常,之间用逗号隔开。
示例:throws关键字
//通过throws关键字在方法参数之后声明异常
public static void divide() throws Exception{
Scanner input = new Scanner(System.in);
System.out.print("请输入被除数:");
int a = input.nextInt();
System.out.print("请输入除数:");
int b = input.nextInt();
System.out.print("%d / %d = %d",a,b,a/b);
}
//方法的调用者在调用方法时,可以根据throw关键字声明的异常得知在该方法可能发生哪些异常,然后做出相应的处理方式。要么捕获异常,要么继续抛出异常
public class test{
public static void main(Strint[] args){
try{
divide();
}catch(Exception e){
System.err.println("出现错误:被除数和除数必须是整数,除数不能为零");
}
}
}
//如果不处理异常,则继续抛出异常
public static void main(Stringp[] args)throws Exception{
divide();
}
//main方法抛出的异常将由Java虚拟机处理。怎么处理?你猜。
抛出异常——throw关键字
在程序的运行过程中,出来系统自动抛出的异常,还有许许多多是系统不会发生的问题,比如说年龄不在范围内,输入的性别不是男或女等,此时需要的是程序员而不是系统来自行抛出异常。
//示例:throw抛出异常
public class Test {
static Logger log = Logger.getLogger(Test.class);
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
System.out.print("请输入课程代号(1~3之间的数字):");
try {
int number = input.nextInt();
//判断输入的数字是否正确
if (number<1||number>3) {
//如果不正确则通过throw关键字抛出异常,并在catch中捕获该异常
throw new IllegalArgumentException("输入的数字范围不正确!");
}
switch (number) {
case 1:
System.out.println("C#编程");
break;
case 2:
System.out.println("Java编程");
break;
case 3:
System.out.println("SQL基础");
break;
}
//捕获上面通过throw关键字抛出的异常
}catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}catch (Exception e) {
System.out.println("未知异常!");
}finally{
System.out.println("执行完毕,感谢使用本程序!");
}
}
}
到此,异常的5个关键字解释完毕。
最后一点:异常的分类
Throwable:所有的异常类型都是Throwable类的子类,它派生两个子类,即Error和Exception。
Error:表示仅靠程序本身无法恢复的严重错误,如内存溢出动态链接失败、虚拟机错误。应用程序不应该抛出这种类型的异常(一般由虚拟机抛出)。假如出现这种错误,除了尽力使程序安全退出外,在其他方面是无能为力的。所以在进行程序设计时,应该更关注Exception类。
Exception:由Java应用程序抛出和处理的非严重错误,如所需的文件找不到、网络连接不通或中断、算数运算出错(如被零除)、数组下标越界、装载了一个不存在的类、对null对象操作、类型转换异常等。它的各种不同子类分别对应不同类型的异常。
运行时异常:包括RuntimeException及其所有子类,不要求程序必须对它们做处理。
Checked异常(非运行时异常/检查异常):除了运行时异常外的其他由Exception继承来的异常类。程序必须捕获或者抛出这种异常,否则会出现编译错误,无法通过编译。处理方式包括两种:通过try-catch在当前位置捕获并处理异常;通过throws声明抛出异常,交给上一级调用方法处理。