Java语言程序设计第五讲,异常处理
学习Java变成过程中我们遇到过许多程序报错现象
之后我们会查看报错原因,对代码进行有针对性的修改从而使其恢复正常
这就是异常处理的目的和用途:计算机提供准确的错徐信息,操作者则根据实际情况提供错误的应对策略与手段
在具体学习异常之前先来了解一下Java的异常处理机制:
1,操作者把可能会发生错误的代码放进try语句块中
2,当程序检测到出现了一个错徐时会抛出一个异常对象,异常处理代码会捕获并处理这个错误(catch语句块中的代码用于处理错误)
3,当异常发生时,程序控制流程有try语句跳转到catch语句块
4,不管是否有异常发生,finally语句块中的语句始终保证被执行
5,如果没有提供合适的异常处理代码JVM会结束掉整个应用程序
异常大体可以分为Error和Exception
Error一般指系统报错,比如打印时没有连接打印机等,通常由JVM处理
Exception又可以分为两类,Check异常和Runtime异常
Check异常是直接派生自Exception的异常,必须被捕获或再次声明抛出
Runtime异常是派生自RuntimeException的异常,使用throw语句可以随时抛出这种异常对象
assert语句允许程序在运行过程中判断某个条件是否满足,不满足时抛出AssertionError
例子: int i = 3;assert i == 10;//抛出异常
OOM Error 指系统内存不足
浮点数在进行除法时允许出现3.7/0,会抛出infinity但是程序继续执行
代码:
public class Main {
public static void main(String[] args) {
try {
try {
throw new ArrayIndexOutOfBoundsException();
}
catch(ArrayIndexOutOfBoundsException e) {
System.out.println( "ArrayIndexOutOfBoundsException" + "/内层try-catch");
}
throw new ArithmeticException();
}
catch(ArithmeticException e) {
System.out.println("发生ArithmeticException");
}
catch(ArrayIndexOutOfBoundsException e) {
System.out.println( "ArrayIndexOutOfBoundsException" + "/外层try-catch");
}
}
}
运行结果:
系统捕获ArrayIndexOutOfBoundsException();异常后跳转到catch执行System.out.println( "ArrayIndexOutOfBoundsException" + "/内层try-catch");语句,之后捕获ArithmeticException();异常,跳转到catch执行System.out.println("发生ArithmeticException");语句
代码:
public class Main {
public static void main(String[] args) {
try {
try {
throw new ArrayIndexOutOfBoundsException();
}
catch(ArithmeticException e) {
System.out.println( "ArrayIndexOutOfBoundsException" + "/内层try-catch");
}
throw new ArithmeticException();
}
catch(ArithmeticException e) {
System.out.println("发生ArithmeticException");
}
catch(ArrayIndexOutOfBoundsException e) {
System.out.println( "ArrayIndexOutOfBoundsException" + "/外层try-catch");
}
}
}
运行结果:
系统捕获ArrayIndexOutOfBoundsException();异常后为找到与之匹配的catch,于是跳转到外层寻找与之匹配的catch,执行System.out.println( "ArrayIndexOutOfBoundsException" + "/外层try-catch");语句
代码:
public class Main {
public static void main(String args[]) {
int result;
try {
System.out.println("in Level 1");
try {
System.out.println("in Level 2");
// result=100/0; //Level 2
try {
System.out.println("in Level 3");
result=100/0; //Level 3
}
catch (Exception e) {
System.out.println("Level 3:" + e.getClass().toString());
}
finally {
System.out.println("In Level 3 finally");
}
// result=100/0; //Level 2
}
catch (Exception e) {
System.out.println("Level 2:" + e.getClass().toString());
}
finally {
System.out.println("In Level 2 finally");
}
// result = 100 / 0; //level 1
}
catch (Exception e) {
System.out.println("Level 1:" + e.getClass().toString());
}
finally {
System.out.println("In Level 1 finally");
}
}
}
运行截图:
在第三层遇到result=100/0;并抛出异常之后调用catch输出System.out.println("Level 3:" + e.getClass().toString())语句,之后catch语句不再执行,执行完所有的finally语句后结束程序运行
特别,当有多层finally语句嵌套时,异常在不同层次抛出,在不同位置抛出,肯导致不同的finally语句执行顺序
例如上一段代码如果异常在level2 抛出,则运行结果为:
代码:
public class Main {
public static void main( String args[] ) {
try {
method1();
}
catch ( Exception e ) {
System.err.println( e.getMessage() + "\n" );
e.printStackTrace();
}
}
public static void method1() throws Exception {
method2();
}
public static void method2() throws Exception {
method3();
}
public static void method3() throws Exception {
throw new Exception( "Exception thrown in method3" );
}
}
运行结果:
说实话看到运行结果的时候有被吓到……
言归正传,method1();抛出异常,之后printStackTrace()按照method1();被调用的吮吸一次抛出异常路径
在throws语句中声明的异常成为受控的异常,通常直接派生自Exception类
RuntimeException(其基类为Exception)和Error(其基类为Throwable)称为非受控的异常,这种异常不用在throws语句中声明
一个方法可以抛出多个受控的异常,此时在此方法调用语句处只要catch其中任何一个异常代码就可以顺利编译
子类的throws语句抛出的异常不能是其基类同名方法抛出的异常对象的父类
public class CatchWho { public static void main(String[] args) { try { try { throw new ArrayIndexOutOfBoundsException(); } catch(ArrayIndexOutOfBoundsException e) { System.out.println( "ArrayIndexOutOfBoundsException" + "/内层try-catch"); } throw new ArithmeticException(); } catch(ArithmeticException e) { System.out.println("发生ArithmeticException"); } catch(ArrayIndexOutOfBoundsException e) { System.out.println( "ArrayIndexOutOfBoundsException" + "/外层try-catch"); } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!