乐趣区

关于linux:聊聊Java中的异常及处理

前言

在编程中异样报错是不可避免的。特地是在学习某个语言初期,看到异样报错就抓耳挠腮,经常开玩笑说编程 1 分钟,改 bug1 小时。明天就让咱们来看看什么是异样和怎么正当的解决异样吧!

异样与 error 介绍

上面还是先让咱们来看一下基本概念吧!

异样 指程序运行过程中呈现的非正常景象,例如用户输出谬误、除数为零、须要解决的文件不存在、数组下标越界等。异样机制实质就是当程序呈现谬误,程序平安退出的机制。在 Java 的异样解决机制中,引进了很多用来形容和解决异样的类,称为异样类。异样类定义中蕴含了该类异样的信息和对异样进行解决的办法。

​ Java 是采纳面向对象的形式来解决异样的。处理过程:

  1. 抛出异样:在执行一个办法时,如果产生异样,则这个办法生成代表该异样的一个对象,进行以后执行门路,并把异样对象提交给 JRE。
  2. 捕捉异样:JRE 失去该异样后,寻找相应的代码来解决该异样。JRE 在办法的调用栈中查找,从生成异样的办法开始回溯,直到找到相应的异样解决代码为止。

让咱们来看看后面所讲到的异样类到底是个什么货色!

其实所有的异样对象都是派生于 Throwable 类的一个实例。如果内置的异样类不可能满足需要,还能够创立本人的异样类。所有异样的根类为 java.lang.Throwable。看看它的家族长什么样。

Throwable 类上面次要是两大门派。ErrorException

  • Error是程序无奈解决的谬误,示意运行应用程序中较重大问题,零碎 JVM 曾经处于不可复原的解体状态中。例如,说内存溢出和线程死锁等零碎问题。
  • Exception是程序自身可能解决的异样。

    Exception 类是所有异样类的父类,其子类对应了各种各样可能呈现的异样事件。通常 Java 的异样可分为:

    1. RuntimeException 运行时异样
    2. CheckedException 已查看异样

上面咱们来钻研钻研这两个异样。

RuntimeException 和 CheckedException 异同

首先咱们先来看看什么是 运行时异样

这类异样通常是由编程谬误导致的,所以在编写程序时,并不要求必须应用异样解决机制来解决这类异样, 而是常常须要通过减少“逻辑解决来防止这些异样”。

比方以下常见的几种异样:

ArithmeticException 异样

 int b=0;
 System.out.println(1/b);
 // 解决:if(b!=0){System.out.println(1/b);
   }

NumberFormatException 异样

String str = "1234abcf";
System.out.println(Integer.parseInt(str));
// 解决:Pattern p = Pattern.compile("^\\d+$");
Matcher m = p.matcher(str);
if (m.matches()) { // 如果 str 匹配代表数字的正则表达式, 才会转换
    System.out.println(Integer.parseInt(str));
}

ClassCastException 异样

Animal a=new Dog();
Cat c=(Cat)a;
// 解决:if (a instanceof Cat) {Cat c = (Cat) a;
}

这里再补充两点,不便大家更好的了解 java 异样的机制和处理过程。

  1. 在办法抛出异样之后,运行时零碎将转为寻找适合的异样处理器(exception handler)。潜在的异样处理器是异样产生时顺次存留在调用栈中的办法的汇合。当异样处理器所能解决的异样类型与办法抛出的异样类型相符时,即为适合的异样处理器。
  2. 运行时零碎从产生异样的办法开始,顺次回查调用栈中的办法,直至找到含有适合异样处理器的办法并执行。当运行时零碎遍历调用栈而未找到适合的异样处理器,则运行时零碎终止。同时,意味着 Java 程序的终止。

下面咱们讲述了什么是运行时异样以及一些解决形式,上面就再来看看什么是 已查看异样 吧!

所有不是 RuntimeException 的异样,统称为 Checked Exception,又被称为“已查看异样”,如 IOException、SQLException 等以及用户自定义的 Exception 异样。这类异样在编译时就必须做出解决,否则无奈通过编译。

通常异样的解决形式有两种:

  1. 应用“try/catch”捕捉异样
  2. 应用“throws”申明异样。

上面就来具体的聊聊吧!

异样的解决

下面曾经提了,异样解决通常有 2 种形式。先看看捕捉异样吧。

捕捉异样 是通过 3 个关键词来实现的:try-catch-finally。用 try 来执行一段程序,如果出现异常,零碎抛出一个异样,能够通过它的类型来捕获 (catch) 并解决它,最初一步是通过 finally 语句为异样解决提供一个对立的进口,finally 所指定的代码都要被执行。

这个捕捉异样其实也是咱们在面试的时候会常常碰到的问题。上面咱们别离再来对各个局部做一个简略的提醒吧!

  • try

一个 try 语句必须带有至多一个 catch 语句块或一个 finally 语句块。当异样解决的代码执行完结当前,不会再回到 try 语句去执行尚未执行的代码。

  • catch

每个 try 语句块能够随同一个或多个 catch 语句,用于解决可能产生的不同类型的异样对象。在此介绍一些罕用的办法,这些办法均继承自 Throwable 类。

  1. toString ()办法,显示异样的类名和产生异样的起因。
  2. getMessage()办法,只显示产生异样的起因,但不显示类名。
  3. printStackTrace()办法,用来跟踪异样事件产生时堆栈的内容。

这里有一个须要特地留神的中央,那就是 catch 捕捉异样时的捕捉程序:

如果异样类之间有继承关系,在程序安顿上就需注意。越是顶层的类,越放在上面,再不然就间接把多余的 catch 省略掉。也就是说先捕捉子类异样再捕捉父类异样。

  • finally

finally 语句块中始终都要执行,除了遇到了 System.exit(0)完结程序运行。针对这个个性,所以咱们通常在 finally 中关闭程序块已关上的资源,比方:敞开文件流、开释数据库连贯等。

即便 try 和 catch 块中存在 return 语句,finally 语句也会执行。是在执行完 finally 语句后再通过 return 退出。

在这里就有一道十分经典的一个面试题。

public class Test {public static void main(String[]args) {System.out.println(new Test().test());;
    }
    static int test(){
       int x = 1;
       try{retun x;}finally{System.out.print("jdbk"+ ++x);
       }
    }
}
// 问输入后果?

先解释哈这里存在的玄妙吧!

看了下面的讲述,咱们都晓得了当 try 和 catch 中有 return 时,finally 依然会执行,所以失常逻辑来说此题的答案应该是“jdbk2 2”, 但这里存在一个陷阱,那就是:

finally 是在 return 前面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保 存起来,不论 finally 中的代码怎么样,返回的值都不会扭转,任然是之前保留的值),所以函数返回值是 在 finally 执行前确定的。因而正确答案应该是:“jdbk2 1”。

还有一点须要留神的就是:finally 中最好不要蕴含 return,否则程序会提前退出,返回值不是 try 或 catch 中保留的返回值。

接下来再来讲讲 申明异样 吧,它相对来说就比较简单了。

在一些状况下,以后办法并不需要解决产生的异样,而是向上传递给调用它的办法解决。如果一个办法抛出多个已查看异样,就必须在办法的首部列出所有的异样,之间以逗号隔开。

public static void readFile(String fileName) throws FileNotFoundException,IOException {}

须要留神的中央就是:

  1. 在办法重写中申明异样时:子类重写父类办法时,如果父类办法有申明异样,那么子类申明的异样范畴不能超过父类申明的范畴。
  2. 申明异样咱们个别在 server 层中。在 controller 层或则数据拜访层个别是捕捉异样。

自定义异样

咱们为什么要自定义异样?还不是因为在程序中,可能会遇到 JDK 提供的任何规范异样类都无奈充沛形容分明咱们想要表白的问题。此时咱们就能够创立本人的异样类,即自定义异样类。

那咱们怎么自定义异样类呢?置信你看了下面的异样类的家族图应该就猜到了。不错,自定义异样类只需从 Exception 类或者它的子类派生一个子类即可。如果你继承 Exception 类,则为受查看异样,必须对其进行解决; 如果不想解决,能够让自定义异样类继承运行时异样 RuntimeException 类。通常咱们自定义异样类应该蕴含 2 个结构器:一个是默认的结构器,另一个是带有详细信息的结构器。这里举一个例子。

/**IllegalAgeException:非法年龄异样,继承 Exception 类 */
class IllegalAgeException extends Exception {
    // 默认结构器
    public IllegalAgeException() {}
    // 带有详细信息的结构器,信息存储在 message 中
    public IllegalAgeException(String message) {super(message);
    }
}

   public void setAge(int age) throws IllegalAgeException {if (age < 0) {throw new IllegalAgeException("人的年龄不应该为正数");
        }
        this.age = age;
    }

最初给大家讲述一点应用异样机制的倡议:

1. 要防止应用异样解决代替错误处理,这样会升高程序的清晰性,并且效率低下。

2. 解决异样不能够代替简略测试 — 只在异常情况下应用异样机制。

3. 不要进行小粒度的异样解决 — 应该将整个工作包装在一个 try 语句块中。

4. 异样往往在高层解决。


最初,最近很多小伙伴找我要Linux 学习路线图,于是我依据本人的教训,利用业余时间熬夜肝了一个月,整顿了一份电子书。无论你是面试还是自我晋升,置信都会对你有帮忙!

收费送给大家,只求大家金指给我点个赞!

电子书 | Linux 开发学习路线图

也心愿有小伙伴能退出我,把这份电子书做得更完满!

有播种?心愿老铁们来个三连击,给更多的人看到这篇文章

举荐浏览:

  • 干货 | 程序员进阶架构师必备资源免费送
  • 神器 | 反对搜寻的资源网站
退出移动版