Java异常(超详细!)
2021/5/3 14:25:13
本文主要是介绍Java异常(超详细!),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1、什么是异常,java提供异常处理机制有什么用?
- 什么是异常:程序执行过程中的不正常情况。
- 异常的作用:增强程序的
健壮性
。
eg.
public class ExceptionTest01 { public static void main(String[] args) { int a = 10; int b = 0; // 实际上JVM在执行到此处的时候,会new异常对象:new ArithmeticException("/ by zero"); // 并且JVM将new的异常对象抛出,打印输出信息到控制台了。 int c = a / b; System.out.println(a + "/" + b + "=" + c); // 此处运行也会创建一个:ArithmeticException类型的异常对象。 System.out.println(100 / 0); } }
2、java语言中异常是以什么形式存在的呢?
异常在java中以 类
的形式存在,每一个 异常类 都可以创建 异常对象。
eg.
public class ExceptionTest02 { public static void main(String[] args) { // 通过“异常类”实例化“异常对象” NumberFormatException nfe = new NumberFormatException("数字格式化异常!"); // java.lang.NumberFormatException: 数字格式化异常! System.out.println(nfe); } }
1、补充:
public class ExceptionTest03 { public static void main(String[] args) { System.out.println(100 / 0); // 这里的HelloWorld没有输出,没有执行。 System.out.println("Hello World!"); } }
程序执行到System.out.println(100 / 0);
此处发生了 ArithmeticException
异常,底层 new
了一个ArithmeticException异常对象,然后抛出了。
由于是 main方法
调用了100 / 0,所以这个异常ArithmeticException抛给了main方法。
main方法没有处理,将这个异常自动抛给了 JVM
。JVM最终终止程序的执行。
此时System.out.println("Hello World!");
并不会执行。
注意:
ArithmeticException
继承 RuntimeException
,属于 运行时异常
。在编写程序阶段不需要对这种异常进行预先的处理。
eg.
public class ExceptionTest04 { public static void main(String[] args) { // main方法中调用doSome()方法 // 因为doSome()方法声明位置上有:throws ClassNotFoundException // 我们在调用doSome()方法的时候必须对这种异常进行预先的处理。 // 如果不处理,编译器就报错。 //编译器报错信息: Unhandled exception: java.lang.ClassNotFoundException doSome(); } /** * doSome方法在方法声明的位置上使用了:throws ClassNotFoundException * 这个代码表示doSome()方法在执行过程中,有可能会出现ClassNotFoundException异常。 * 叫做类没找到异常。这个异常直接父类是:Exception,所以ClassNotFoundException属于编译时异常。 * @throws ClassNotFoundException */ public static void doSome() throws ClassNotFoundException{ System.out.println("doSome!!!!"); } }
解决方法一、throws上报给方法调用者(推卸责任:调用者知道)
public class ExceptionTest04 { public static void main(String[] args) throws ClassNotFoundException { doSome(); } public static void doSome() throws ClassNotFoundException{ System.out.println("doSome!!!!"); } }
解决方法二、try…catch捕捉,处理(调用者是不知道)
public class ExceptionTest04 { public static void main(String[] args) { try { doSome(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static void doSome() throws ClassNotFoundException{ System.out.println("doSome!!!!"); } }
3、异常处理方式
3.1 throws
在方法声明的位置上使用 throws
关键字抛出,谁调用我这个方法,我就抛给谁。抛给 调用者
来处理。
这种处理异常的态度:上报。
3.2 try…catch
这个异常不会上报,自己把这个事儿处理了。
异常抛到此处为止,不再上抛了。
注意:
- 只要异常没有捕捉,采用上报的方式,此方法的
后续代码不会执行
。 - try语句块中的某一行出现异常,该行
后面的代码不会执行
。 - try…catch捕捉异常之后,后续代码可以执行。
eg.
private static void m1() throws FileNotFoundException { System.out.println("m1 begin"); m2(); // 以上代码出异常,这里是无法执行的。 System.out.println("m1 over"); }
try { m1(); // m1方法出异常,下面代码不执行。 System.out.println("hello world!");//不执行 } catch (FileNotFoundException e){ //异常处理 System.out.println("出异常了!!"); System.out.println(e); } System.out.println("hello world"); //会执行
注意:
- 一般不建议在main方法上使用throws,因为这个异常如果真正的发生了,一定会抛给JVM。JVM只有终止。
- 一般main方法中的异常建议使用try…catch进行捕捉。
注意:
try { } catch (ClassNotFoundException e) { e.printStackTrace(); }
这个分支中可以使用e引用,e引用
保存的内存地址是那个new出来 异常对象的内存地址
。
4、在以后开发中,处理编译时异常,应该上报还是捕捉呢?
- 如果希望调用者来处理,选择throws上报。
- 其它情况使用捕捉的方式。
5、深入try…catch
- catch后面的小括号中的类型可以是
具体的异常类型
,也可以是该异常类型的父类型
。 - catch可以写多个。建议catch的时候,精确的一个一个处理。这样有利于程序的调试。
- catch写多个的时候,从上到下,必须遵守
从小到大
。
eg.
try { FileInputStream fis = new FileInputStream("D:\\Download\\Javabean-addperson案例解析.docx"); } catch(FileNotFoundException e) { System.out.println("文件不存在!"); } 等同于 try { FileInputStream fis = new FileInputStream("D:\\Download\\Javabean-addperson案例解析.docx"); } catch(Exception e) {// 多态:Exception e = new FileNotFoundException(); System.out.println("文件不存在!"); }
try { FileInputStream fis = new FileInputStream("D:\\Download\\Javabean-addperson案例解析.docx"); fis.read(); } catch(IOException e){ System.out.println("读文件报错了!"); } catch(FileNotFoundException e) { System.out.println("文件不存在!"); }
- JDK8的新特性:
catch() 异常间可以自小到大用|
分割
eg.
try { //创建输入流 FileInputStream fis = new FileInputStream("D:\\Download\\Javabean-addperson案例解析.docx"); // 进行数学运算 System.out.println(100 / 0); // 这个异常是运行时异常,编写程序时可以处理,也可以不处理。 } catch(FileNotFoundException | ArithmeticException | NullPointerException e) { System.out.println("文件不存在?数学异常?空指针异常?都有可能!"); }
6、异常两个重要方法
方法名 | 作用 |
---|---|
String getMessage() | 返回异常的详细消息字符串 |
void printStackTrace() | 追踪堆栈异常信息(采用异步线程) |
7、finally字句
在finally子句中的代码是最后执行的,并且是 一定会执行
的,即使try语句块中的代码出现了异常。
finally子句必须和try一起出现,不能单独编写。
7.1 finally语句通常使用在哪些情况下呢?
通常在finally语句块中完成 资源的释放/关闭
。
eg.
public class ExceptionTest10 { public static void main(String[] args) { FileInputStream fis = null; // 声明位置放到try外面。这样在finally中才能用。 try { fis = new FileInputStream("D:\\Download\\Javabean-addperson案例解析.docx"); String s = null; // 这里一定会出现空指针异常! s.toString(); System.out.println("hello world!"); // 流使用完需要关闭,因为流是占用资源的。 // 即使以上程序出现异常,流也必须要关闭! // 放在这里有可能流关不了。 //fis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch(IOException e){ e.printStackTrace(); } catch(NullPointerException e) { e.printStackTrace(); } finally { System.out.println("hello 浩克!"); // 流的关闭放在这里比较保险。 // finally中的代码是一定会执行的。 // 即使try中出现了异常! if (fis != null) { // 避免空指针异常! try { // close()方法有异常,采用捕捉的方式。 fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
7.2try和finally联用,没有catch
eg.
public class ExceptionTest11 { public static void main(String[] args) { try { System.out.println("try..."); return; } finally { System.out.println("finally..."); } // 这里不能写语句,因为这个代码是无法执行到的。 //System.out.println("Hello World!"); } }
以下代码的执行顺序:
- 先执行try…
- 再执行finally…
- 最后执行 return (return语句只要执行方法必然结束。)
注意:
- try不能单独使用。
- try finally可以联合使用。
- 放在finally语句块中的代码是一定会执行的
7.3 finally子句失效
System.exit(0);
只有这个可以治finally。
public class ExceptionTest12 { public static void main(String[] args) { try { System.out.println("try..."); // 退出JVM System.exit(0); // 退出JVM之后,finally语句中的代码就不执行了! } finally { System.out.println("finally..."); } } }
7.4 finally面试题
public class ExceptionTest13 { public static void main(String[] args) { int result = m(); System.out.println(result); //100 } /* java语法规则(有一些规则是不能破坏的,一旦这么说了,就必须这么做!): java中有一条这样的规则: 方法体中的代码必须遵循自上而下顺序依次逐行执行(亘古不变的语法!) java中海油一条语法规则: return语句一旦执行,整个方法必须结束(亘古不变的语法!) */ public static int m(){ int i = 100; try { // 这行代码出现在int i = 100;的下面,所以最终结果必须是返回100 // return语句还必须保证是最后执行的。一旦执行,整个方法结束。 return i; } finally { i++; } } }
反编译之后的效果:
public static int m(){ int i = 100; int j = i; i++; return j; }
7.5 final finally finalize有什么区别?
- final 关键字
- final修饰的
类
无法继承 - final修饰的
方法
无法覆盖 - final修饰的
变量
不能重新赋值。
- finally 关键字
- finally 和try一起联合使用。
- finally语句块中的代码是必须执行的。
- finalize 标识符
- 是一个Object类中的方法名。
- 这个方法是由垃圾回收器GC负责调用的
8、自定义异常(开发中常用)
8.1前言
SUN提供的JDK内置的异常肯定是不够的用的。在实际的开发中,有很多业务,这些业务出现异常之后,JDK中都是没有的。和业务挂钩的。因此需要自定义异常。
8.2自定义异常步骤
- 第一步:编写一个类继承
Exception
或者RuntimeException
. - 第二步:提供两个
构造方法
,一个无参数的,一个带有String参数的。
eg.
//栈操作异常:自定义异常! public class StackOperationException extends Exception{ // 编译时异常! public MyStackOperationException(){ } public MyStackOperationException(String s){ super(s); } }
9、方法覆盖,时遗留的问题
- 重写之后的方法不能比重写之前的方法抛出更多(更宽泛)的异常,可以更少。方法覆盖
class Animal { public void doSome(){ } public void doOther() throws Exception{ } } class Cat extends Animal { // 编译正常。 public void doSome() throws RuntimeException{ } // 编译报错。 /*public void doSome() throws Exception{ }*/ // 编译正常。 /*public void doOther() { }*/ // 编译正常。 /*public void doOther() throws Exception{ }*/ // 编译正常。 public void doOther() throws NullPointerException{ } }
注意:
一般不会这样考虑,方法覆盖复制一份,然后重写就好了。
10、总结异常中的关键字
- 异常捕捉:
- try
- catch
- finally
- throws 在方法声明位置上使用,表示上报异常信息给调用者。
- throw 手动抛出异常!
eg.
public void pop() throws StackOperationException { if(index < 0){ throw new MyStackOperationException("弹栈失败,栈已空!");//手动抛出异常 } }
该方法index < 0时手动抛出异常,然后在方法里没有处理,上报给调用者,让调用者处理!
这篇关于Java异常(超详细!)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-26手写消息中间件:从零开始的指南
- 2024-11-26Java语音识别项目资料:新手入门教程
- 2024-11-26JAVA语音识别项目资料:新手入门教程
- 2024-11-26Java语音识别项目资料:入门与实践指南
- 2024-11-26Java云原生资料入门教程
- 2024-11-26Java云原生资料入门教程
- 2024-11-26Java云原生资料:新手入门教程
- 2024-11-25Java创意资料:新手入门的创意学习指南
- 2024-11-25JAVA对接阿里云智能语音服务资料详解:新手入门指南
- 2024-11-25Java对接阿里云智能语音服务资料详解