Java学习异常
异常:就是Java代码在运行时期发生的问题
异常的继承体系
Throwable类是所有错误和异常的祖宗类
在Throwable类下有两大子类:Error类和Exception类
Error类:指在程序运行期间发生了某种错误,没有具体的处理办法,程序就结束了。
Error错误的发生一般都是系统级别的,只能修改代码
Exception类:编译时期异常,一般是编译Java程序时出现的问题
在Exception下的RuntimeException子类,是运行时期异常,是Java程序在运行时期发生的问题
异常产生的过程分析
1 2 3 4 5 6 7 8 9 10 | public static int getArray( int [] arr) { int i = arr[ 3 ]; return i; } public static void main(String[] args) throws Exception { int [] arr = { 1 , 3 }; int i = getArray(arr); System.out.println(i); } |
过程:1、JVM自动检测到数组越界异常,此时JVM会自动创建一个对象new ArrayIndexOutOfBoundsException(),JVM将异常抛给它的调用者
2、在main方法中找到调用者,一看没有得到处理,就继续往上抛,抛给JVM
3、JVM收到抛出的异常
a:将异常信息以红字的形式打印在控制台上
b:结束程序
所以代码修改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public static int getArray( int [] arr) throws Exception { if (arr == null ) { throw new Exception( "你传进来的数组是null" ); } if (arr.length < 3 ) { throw new Exception( "你传得数组长度太小了,请传三个以上" ); } int i = arr[ 3 ]; return i; } public static void main(String[] args) throws Exception { int [] arr = { 1 , 3 , 5 , 7 }; int i = getArray(arr); System.out.println(i); } |
异常的处理方式
1、throws
2、try.....catch 或 try...catch...finally
在Java中,用throw关键字抛出一个异常对象 throw new 异常类名(参数) 如:throw new Exception();
声明异常throws:异常已经抛出,但是需要需要声明给调用者 在方法后面加上 throws 异常类名1,异常类名2.....
try{
被检测得代码
可能出现异常得代码
}catch(异常类名 变量名){
异常得处理方式
}finally{
必须要执行得代码
}
作用:try检测到有异常得发生,接收到一个异常对象,将异常对象抛给catch代码块处理,catch捕获到这个异常对象,那么就执行处理方式代码
finally代码块里面的内容是一定要执行的,一般是释放资源的,如关闭数据库,关闭文件
多个catch处理的注意事项
多个catch时:1、看抛出的异常是否是平级关系(是否有继承)
如:NullPointerException extends RuntimeException
ArrayIndexOutOfBoundsException extends RuntimeException
如果没有继承就可以随便写
2、如果有上下级关系,就必须把下级放前面,上级放后面
如:Exception 上级
NullPointerException 下级
如果把Exception放到了NullPointerException的前面,若方法中首先抛出的NullPointerException 异常,它会转到catch处,Exception首先接收,就会形 成多态关系(父类引用指向子类对象),那么后面catch中的NullPointerException就会没有作用,编译报错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | public static int getArray( int [] arr) throws NullPointerException, ArrayIndexOutOfBoundsException { if (arr == null ) { // 抛出一个异常对象,谁调用就抛给谁 // 然后声明异常 throws NullPointerException throw new NullPointerException( "你传的数组为空" ); } if (arr.length < 3 ) { throw new ArrayIndexOutOfBoundsException( "你传得数组长度不够" ); } return arr[arr.length - 1 ]; } public static void main(String[] args) { int [] arr = null ; try { int i = getArray(arr); // 异常抛到here System.out.println(i); } catch (NullPointerException ex) { <br> //NullPointerException extends RuntimeException //getMessage()方法打印的是传入的字符串 System.out.println(ex.getMessage()); //printStackTrace()打印的是完整的异常信息,包括类名+字符串+报错位置 ex.printStackTrace(); } catch (ArrayIndexOutOfBoundsException ex) {<br> //ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException<br> //IndexOutOfBoundsException extends RuntimeException //toString方法打印的是完整的异常类名+传入的字符串 System.out.println(ex.toString()); } finally { //finally用于存放释放资源得代码,如:关闭数据库,关闭文件等 System.out.println( "必须要执行得代码" ); } System.out.println( "Game Over" ); } |
运行时期异常和编译时期异常
运行时期异常: 方法中抛出运行时期异常,方法定义中无需throws声明,调用者也无需处理此异常
运行时期异常一旦发生,需要程序人员修改源代码.
RuntimeException和他的所有子类异常,都属于运行时期异常。NullPointerException,ArrayIndexOutOfBoundsException等都属于运行时期异常
编译时期异常:只要调用了抛出异常的方法,但是没有处理,就会编译失败 处理方式(try throws) 必须用throws声明
异常在方法重写中的细节问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Fu{ public void fumethod(){ } } class Zi extends Fu{ public void fumethod(){ try { method(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void method() throws Exception{ } } |
当父类中有异常方法时
子类继承父类重写这个异常方法的时候,注意:
1、子类可以选择不抛出,但是如果子类选择抛出异常 那么你抛出的异常类不得超过你父类的异常,可以是你父类的异常也可以是你父类异常的子类
当父类方法中没有抛异常时
1、你子类重写这个方法也不可以抛异常
2、父类方法中没有抛异常,但是子类重写这个方法时,在方法中调用了带有抛出异常的方法
由于父类没有抛异常,那么只能try catch处理这个异常,不能throws
异常中常用的方法
getMessage方法:返回该异常的详细信息字符串,即异常提示信息
toString方法:返回该异常的名称+详细信息字符串
printStackTrace:在控制台输出该异常的名称+详细信息字符串+异常出现的代码位置
自定义异常类
NullPointerException异常类源代码:
public class NullPointerException extends RuntimeException {
public NullPointerException() {
super();//调用父类构造方法
}
public NullPointerException(String s) {
super(s);//调用父类具有异常信息的构造方法
}
}
格式:
Class 异常名 extends Exception{ //或继承RuntimeException
public 异常名(){
}
public 异常名(String s){
super(s);
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package com.oracle.demo1; public class Test { public static void main(String[] args) { // 定义一个方法 计算平均数的方法 System.out.println(avgnum( 2 , - 4 , 5 , 6 )); } public static double avgnum( double ... b) { double sum = 0 ; for ( int i = 0 ; i < b.length; i++) { if (b[i] < 0 ) { throw new FuShuException( "你传入的是负数" ); } sum = sum + b[i]; } return sum / b.length; } } package com.oracle.demo1; public class FuShuException extends RuntimeException { public FuShuException(String s) { super (s); } public FuShuException() { super (); } } |
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· 继承的思维:从思维模式到架构设计的深度解析
· 如何在 .NET 中 使用 ANTLR4
· 后端思维之高并发处理方案
· 理解Rust引用及其生命周期标识(下)
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· 当职场成战场:降职、阴谋与一场硬碰硬的抗争
· ShadowSql之.net sql拼写神器
· Excel百万数据如何快速导入?
· 无需WebView,Vue也能开发跨平台桌面应用