一,异常概述
在程序中,异常可能由程序员没有预料到的各种情况产生,也可能由超出了程序员可控范围的环境因素产生,如用户的坏数据,试图打开一个根本不存在的文件等。在Java中,这种在程序运行的可能出现的一些错误称为异常。异常是一个在程序执行期间发生的事件,它中断了正在执行的程序的正常指令流。
异常处理机制允许程序在出现异常时通过一系列处理机制来对异常进行捕获、处理、抛出等操作。Java中的异常分为两种类型:受检异常和非受检异常。
受检异常指的是在程序编译时就能够确定的异常,它们必须在方法声明时显式地声明,并且在方法中必须进行处理或者抛出。这种异常包括IO异常、SQL异常等。
非受检异常指的是在程序运行时才会出现的异常,也称为运行时异常。这种异常通常是由于程序的逻辑错误或者运行环境异常导致的。非受检异常包括空指针异常、数组越界异常等。
public class Baulk {//创建类
public static void main(String[] args) {//主方法
int result = 3/0;//定义int型变量并赋值
System.out.println(result);//将变量输出
}
}
程序运行的结果报告发生了算数异常ArithmeticException(根据给出的错误提示可知,发生错误是因为在算术表达式"3/0"中,0作为除数出现),系统不再执行下去,提前结束。这种情况就是所说的异常。
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Baulk.main(Baulk.java:7)
二,异常的抛出与捕捉
1,在Java中,如果某个方法抛出异常,既可以在当前方法中进行捕捉,而后处理该异常,也可以将异常向上抛出,交由方法调用者处理
2,抛出异常后,如果不做任何处理,程序就会被终止
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);//输出信息
}
}
结果显示NumberFormatException 数字格式错误
3.捕捉异常
Java语言的异常捕获结构由try、catch和finally 3部分组成。其中,try语句块存放的是可能发生异常的Java语句:catch语句块在try语句块之后,用来激发被捕获的异常;finally语句块是异常处理结构的最后执行部分,无论try语句块中的代码如何退出,都将执行finally语句块
1)语句
try{
//程序代码块
}
catch(Excptiontype1 e){
//对Excptiontype1 的处理
}
catch(Excptiontype2 e){
//对Excptiontype2 的处理
}
...
finally{
//程序代码块
}
2)try-catch语句块
public class Take {
public static void main(String[] args) {
try {
String str = "lili";//定义字符串
System.out.println(str+"年龄是:");//输出的提示信息
int age = Integer.parseInt("20L");//数据类型转换
System.out.println(age);//输出信息
}catch(Exception e) {//catch语句块用来获取异常信息
e.printStackTrace();//输出异常性质
}
System.out.println("program over");//输出信息
}
}
3)finally语句块
完整的异常处理语句一定要包含finally语句,无论程序中有无异常发生,并且无论之前的try-catch语句块是否顺利执行完毕,都会执行finally语句。
注意在以下4种情况下,finally块不会被执行:
1.在finally语句块中发生了异常
2.在前面的代码中使用了System.exit()退出程序
3.程序所有的线程死亡
4.关闭CPU
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);//输出信息
}catch(NumberFormatException e) {
System.out.println("数字格式异常");
}
finally {
System.out.println("程序结束");
}
}
}
三,Java常见的异常类
四、自定义异常
1,使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户只需要继承Exception类即可以自定义异常。
2,在程序中使用自定义异常类,大体可分为以下几个步骤:
1.创建自定义异常类
2.在方法中通过throw关键字抛出异常对象
3.如果在当前抛出异常的方法中处理异常,可以使用try-catch语句块捕获并处理,否则在方 法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作
例题:如何创建自定义异常
public class MyException extends Exception {
//创建自定义异常,继承Exception类
public MyException(String ErrorMessage) {//构造方法
super(ErrorMessage);//super调用父类的构造方法
}
}
例题:自定义异常的抛出与捕捉
public class Tran {//创建类
static int avg(int number1,int number2) throws MyException {//定义方法,抛出异常
//throws抛到调用avgd的地方
if(number1<0 || number2<0) {//判断方法中参数是否满足指定条件
//System.out.println("不可以使用负数");
throw new MyException("不可以使用负数");//错误信息
}
if(number1>100 || number2>100) {//判断方法中参数是否满足指定条件
//System.out.println("不可以大于100");
throw new MyException("不可以大于100");//错误信息
}
return(number1+number2)/2;//将参数的平均值返回
}
public static void main(String[] args) {//主方法
try {//try语句块处理可能出现异常的代码
int result = avg(102, 156);//调用avg()方法
System.out.println(result);//将avg()方法的返回值输出
} catch (MyException e) {
System.out.println(e);//输出异常信息
}
}
}
五,在方法中抛出异常
在Java中,可以在方法中抛出异常来表示程序出现了错误或异常情况。如果在方法中抛出异常,方法必须使用throws关键字声明将要抛出的异常,或者在方法内部使用try-catch语句块来捕获异常并进行处理。
1, 使用throws关键字抛出异常
使用 throws 关键字可以声明一个方法可能抛出的异常,由方法调用者来处理异常。当方法中抛出的异常没有被捕获处理时,异常将沿着调用栈向上抛出,直到被捕获或导致程序崩溃。
public class Shoot{
static void pop() throws NegativeArraySizeException{
//定义方法并抛出NegativeArraySizeException异常
int[] arr = new int[-3];//创建数组
}
public static void main(String[] args){//主方法
try {//try语句处理异常
pop() ;//调用pop ()方法
}catch (NegativeArraySizeException e){
System.out.println ("pop ()方法抛出的异常");//输出异常信息
}
}
}
2,使用throw关键字抛出异常
在Java中,使用throw关键字可以手动抛出一个异常。throw关键字必须和try-catch语句一起使用,否则会出现编译错误。抛出的异常对象可以是任何类型,只需要是Throwable类的子类即可
例题:使用throw关键字捕捉自定义异常
public class Captor {
static int quotient (int x, int y) throwsMyExceptionl{
//定义方法 quotient (),可能会抛出自定义异常 MyException1
if (y < 0){//如果除数 y 小于 0,抛出异常
throw new MyException1 ("除数不能是负数”) ;
}
return x / y; // 否则返回 X 除以 y 的结果
}
public static void main(String[] args) {
try { // 尝试执行代码块中的语句方法
int result = quotient(3, -1);
//调用 quotient (),传入参数 3 和 -1,返回结果保存到变量 result 中
}catch (MyExceptionl e) {
//如果quotient () 方法抛出了自定义异常 MyExceptionl,执行该 catch 代码块
System.out.println(e.getMessage () ) ;// 打印异常信息
}catch (ArithmeticException e) {
// 如果发生了 ArithmeticException 异常,执行该 catch 代码块
System.out.println ("除数不能为0");//打印异常信息
} catch (Exception e)//如果发生了其他异常,执行该 catch 代码块
System.out.println("程序发生了其他异常") ;// 打印异常信息
}
}
}
六,运行时异常
运行时异常是指在程序运行期间可能抛出的异常,通常是由于程序代码本身出现问题所引起的,例如空指针异常、类型转换异常等。这些异常在编译期间不会被检查到,只有在程序运行时才会被抛出。
运行时异常通常可以通过良好的编程习惯和代码设计来避免,例如避免空指针引用、进行类型检查等。在代码中出现运行时异常时,可以通过try-catch语句块来捕捉并处理异常,或者让程序直接崩溃并输出异常信息。
七,异常的使用原则
1.抛出异常的地方需要考虑异常的处理,包括自己处理和向上层抛出;
2.不要在 finally 块中使用 return,因为 finally 块中的 return 语句会覆盖 try 块中的 return 语句;
3.捕捉异常时,应该从小到大捕捉,即先捕捉子类异常,再捕捉父类异常;
4.不要捕捉 Throwable 类型的异常,因为 Throwable 类型包括 Error 和 Exception,Error 表示严重错误,Exception 表示程序运行时出现异常,两者的处理方式不同;
5.不要在循环体内抛出异常,因为这样会影响程序的性能,应该尽可能避免在循环体内抛出异常