异常

什么是异常

在程序执行中,任何中断正常程序流程的条件就是错误或异常。例如,程序运行发生下列情况时,会出现异常:
1.想打开的文件不存在
2.网络连接中断
3.接受了不符合逻辑的操作数
4.系统资源不足

Throwable类是Java语言中所有错误或异常的超类。
Error、RuntimeException及其子类、其它异常表示一种运行时的困难,它通常由环境效果引起,可以进行处理。
image.png

在Java编程语言中,错误类(Error)定义被认为是不能恢复的严重错误条件(如资源耗尽)。在大多数情况下,当遇到这样的错误时,建议让程序中断,应用程序一般不对此问题进行处理。
异常处理允许程序捕获异常(Exception),处理它们,然后继续程序执行。它是分层把关,因此,错误情况不会介入到程序的正常流程中。

异常分类

image.png
空指针异常

  1. public class Main {
  2. public static void main(String[] args) {
  3. String str = nul1;
  4. System.out.println(str.length());
  5. }
  6. }

image.png
算数异常

  1. public class Main {
  2. public static void main(String[] args){
  3. int divisor=10;
  4. double quotient =0d;
  5. quotient =divisor/0;
  6. System.out.println("quotient="+quotient);
  7. }
  8. }

image.png

程序中的异常从哪里来
1、程序运行过程中,运行环境检测到错误抛出的异常。
2、程序调用的方法可能会抛出异常。
如:File类的方法createTempFile
java语法中,有一些方法定义的时候有可能会出错,所以在编写的时候就有异常的提示
Ctrl+左键单击 可以进去看方法的定义
看到createTempFile方法定义中就抛出了异常,那我们就需要捕获异常(catch)或者向上抛(throw)
image.png
image.png

注:异常对象包含有关异常的信息,包括它的类型和出错时程序的状态。
向上抛异常:
这个有点不负责任,你写代码有可能会出错,谁调用了main方法才会去处理

  1. import java.io.File;
  2. import java.io.IOException;
  3. public class Main {
  4. public static void main(String[] args) throws IOException {
  5. File.createTempFile("aaa","bbb");
  6. }
  7. }

捕获异常:

就是在调用方法时,设置好异常捕获语句块,出了问题会直接进入异常处理

  1. import java.io.File;
  2. import java.io.IOException;
  3. public class Main {
  4. public static void main(String[] args){
  5. try {
  6. File.createTempFile("aaa","bbb");
  7. } catch (IOException e) {
  8. e.printStackTrace();
  9. }
  10. }
  11. }

eg:

  1. public class Main {
  2. public static void main(String[] args) {
  3. String str = null;
  4. int length = 0;
  5. try {
  6. length = str.length();//空值调用方法
  7. System.out.println(length);
  8. } catch (NullPointerException e) {
  9. System.out.println("Exception occured:" + e);
  10. } finally {
  11. System.out.println("Completed!");
  12. }
  13. }
  14. }

image.png
eg:

  1. import java.io.File;
  2. import java.io.IOException;
  3. public class Main {
  4. public static void main(String[] args) {
  5. try{
  6. File tmp= File.createTempFile("abc","log");
  7. System.out.println(tmp. getAbsolutePath());
  8. } catch(IOException e){
  9. System. out. println(e. getMessage());
  10. }
  11. }
  12. }

image.png

使用try-catch捕获异常

使用try-catch捕获异常
语法格式:

  1. try{
  2. //try代码块中的代码有可能抛出异常
  3. }catchMyExceptionType e){
  4. //处理try代码块中抛出的MyExceptionType类型的异常实例e
  5. }finally{
  6. //无论是否有异常抛出,此部分代码总是被最后执行
  7. }

多异常情况下的catch

  1. public class Main {
  2. public static void main(String[] args) {
  3. String str = null;
  4. int length = 0;
  5. try {
  6. length = str.length();//空值调用方法System.out.printin(length);
  7. } catch (NullPointerException e) {
  8. System.out.println("Exception occured:" + e);
  9. } catch (ArithmeticException e) {
  10. System.out.println("Exception occured:" + e);
  11. } catch (Exception e) {
  12. System.out.println("Exception occured:" + e);
  13. }
  14. }
  15. }

image.png

finally语句

finally语句在try/catch/finally是一个可选的部分。
finally语句定义一个总是执行的代码块,而不考虑异常是否波捕获。所以它提供了在try/catch代码块执行结束后的后处里机制。下面一个用户登录验证的模拟过程:

  1. try{
  2. 查找用户;
  3. 匹配密码
  4. }catchAccountNotFoundException e){
  5. 处理没有发现账号的异常;
  6. }catchPasswordMismatchException e
  7. 处理账号密码不匹配的异常;
  8. }finally{
  9. 登记本次访问;
  10. }

注意:一个try块可以不执行finally子句就能够退出的唯一方法是通过调用System.exit()方法来实现的。

捕获所有异常

所有异常使用Exception

  1. catchException e){
  2. ...
  3. }

image.png

自定义异常

用户定义异常是通过扩展Exception类或子类来创建的一种具有特殊用途的子类,这种异常类可以包含一个“普通”类所包含的任何东西

  1. public class Main {
  2. public static void main(String[] args) {
  3. class AccountNotFoundException extends Exception {
  4. String account;
  5. public AccountNotFoundException() {
  6. super("This account has not found.");
  7. }
  8. public AccountNotFoundException(String account) {
  9. super("This account about" + account + "has not found.");
  10. this.account = account;
  11. }
  12. public String getAccount () {
  13. return this.account;
  14. }
  15. }
  16. }
  17. }

方法声明中的异常

  1. public class AccountNotFoundException extends Exception {
  2. String account;
  3. public AccountNotFoundException(){
  4. super("this account has not found");
  5. }
  6. public AccountNotFoundException(String account){
  7. super("this account about"+account+"has not found");
  8. }
  9. public String getAccount(){
  10. return this.account;
  11. }
  12. }
  1. public class User {
  2. public void login(String account, String password)
  3. throws AccountNotFoundException {
  4. boolean accountExisted = false;//默认帐号不存在,改成true就登陆成功
  5. String otherPassword;
  6. //此处可插入查询帐号的代码
  7. if (false==accountExisted) {//如果帐号不存在,抛出异常,程序中断
  8. throw new AccountNotFoundException(account);
  9. }
  10. }
  11. }
  1. public class Main {
  2. public static void main(String[] args) {
  3. User user = new User();
  4. try {
  5. user.login("account", "password");
  6. } catch (AccountNotFoundException e) {
  7. //插入处理帐号不存在的代码
  8. System.out.println(e.getMessage());
  9. System.exit(-1);
  10. }
  11. //插入登陆成功的代码
  12. System.out.println("登陆成功/");
  13. }
  14. }

image.png

运行结果

  1. public class Main {
  2. static void foo() throws Exception {
  3. throw new Exception();
  4. }
  5. public static void main(String args[]) {
  6. try {
  7. foo();
  8. } catch (Exception e) {
  9. System.exit(0);
  10. } finally {
  11. System.out.println("In finally");
  12. }
  13. }
  14. }

image.png

捕获异常的顺序

那个catch语句块在前面,谁先捕获