前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >【刨根问底】java异常

【刨根问底】java异常

作者头像
田维常
发布2019-08-19 16:15:00
发布2019-08-19 16:15:00
48100
代码可运行
举报
运行总次数:0
代码可运行
Java异常对于开发人员来说接触是非常频繁,处理好程序的异常也是一门艺术或者说是技术,发现身边很多人其实根本没有搞清楚Java异常。想想自己也当做巩固基础,今天就来把java异常模块总结一下。

本文主要内容:

  • 异常的定义
  • 异常的分类
  • java异常关键字
  • 异常常用代码模板
  • 自定义异常

定义

在计算机的世界里,在运行程序时,发生了意料之外的事件,阻止了程序的正常执行,这种情况被称之为异常。

异常的分类

JDK中有一套完整异常机制,所有异常都是Throwable的子类,分为Error(知名异常)和Exception(非致命异常)。

Error

Error是一种特殊的异常,它出现标识着系统发生了不可控制的错误,比如:常见的OutOfMemoryError(内存溢出),StackOverflowError栈溢出。

Exception

Exception又分为checked(受检查)和unchecked(非受检查)异常。

checked受检查的异常是需要在程序中显示处理的异常,否则编译失败。在开发过程中遇到这种异常的时候,一般是要么处理掉该异常,要么直接往上抛。常见的checked异常有:SQLExceptionClassNotFoundException等。

checked异常还可以分为以下两类异常:
  1. 无能为力、引起注意型:针对此类型异常,程序无法处理,如果字段超过表字段长度,数据库表字段不存在等造成的SQLException,这时候最好的方式就是打印出异常错误信息,供开发人员排查问题。
  2. 力所能及,坦然处理型:发生未授权异常UnAuthorizedException,程序可以跳转至权限申请页面。
  3. 可预测异常:就是开发人员可以根据自己的程序大致能猜到的异常。比如:数组越界,IndexOutOfBoundsExceptionNullPointerException等,面对此等异常,最好解决办法就是开发人员做好相应的边界值校验,或者捕获对应异常就行处理。
  4. 需要捕捉异常:比如在使用Dubbo框架进行RPC调用时,容易产生timeout异常DubboTmieoutException,此类异常也是最好显示低捕获,当捕获到相应的异常后可以做一些重试、熔断等操作。

异常关键字

try catch finally throws throw

以上关键字的解释

throws:使用在方法签名参数后 ,向调用此方法的地方抛一个异常。

throw:使用在方法里面,由于某某原因,需要往外跑一个异常,或者是针对某种异常进行转换成自定义异常,然后往外抛自定义异常。

try:不能单独使用,只能结合catch,finally一起使用,try代码块起到见识程序执行过程,如果一旦程序中发生异常则直接跳到catch模块中,如果没有异常发生则直接跳到finally模块中(前提是try+catch+finally)。

catch:结合try一起使用,可以加入finally模块,也可以是多个catch组合.如果try模块中发生异常并且catch(异常类型)刚刚是对应的异常或者范围更大的时候,就会进入catch模块。

finally:结合try使用,或者结合try+catch一起使用。finally模块表示必须执行的模块。不管程序是否发生异常,都会执行finally模块。注意:没有进入finally的情况有:程序执行没有进入try模块、进入try模块,但是程序中出现死循环了或者死锁状态、进入try模块,但是执行了System.exit();

常见代码模板

代码语言:javascript
代码运行次数:0
复制
public class MyException {
    //模板1,方法签名参数后向外抛异常
    public void test() throws Exception {
    }
    //模板2,方法里向外抛异常
    public void test1() {
        throw new Exception();
    }
    //模板3,处理程序异常的三部曲try--catch--finally
    public void test2() {
        try {
            //doSomething
        } catch (Exception ex) {
            
        } finally {
         //最后在处理点事情
        }
    }
    //模板4,发现异常,捕获异常,try--catch
    public void test3() {
        try {
            //doSomething
        } catch (Exception ex) {
            
        }
    }
    //模板 4,发现异常,捕获异常,先捕获范围小的,再捕获范围大的
    public void test4() {
        try {
            //doSomething
        } catch (NullPointerException ex) {
            
        }catch (Exception ex){

        }
    }
    //模板 5,发现异常,捕获异常,先捕获范围小的,再捕获范围大的,最后在处理点事情
    public void test5() {
        try {
            //doSomething
        } catch (NullPointerException ex) {
            
        }catch (Exception ex){
            
        }finally {
          //最后在处理点事情
        }
    }
    //模板6,不管有没有捕获到异常,
    public void test6() {
        try {
            //doSomething
        }  finally {
        //最后在处理点事情
        }
    }
}

自定义异常

在开发过程中难免会想自定义异常,比如说针对某些业务的操作失败,我们如果用其他异常类可能会有歧义,所以使用自定义的异常来和其他异常的区分,也有的时候是针对系统级的,Pay支付模块的异常可以定义成PayException。但是怎么定义呢?Throwable分为Error和Exception,所以如果自定义的异常继承于Error的话行么?因为Error是不可控的,所以通常不会继承与它。通常都是自定义异常继承于Exception或者RuntimeException。如果希望写一个检查性异常类,则需要继承 Exception 类。如果你想写一个运行时异常类,那么需要继承 RuntimeException类。

代码语言:javascript
代码运行次数:0
复制
//自定义异常,继承于Exception
public class CustomException extends Exception {
    public CustomException(String message) {
        super(message);
    }
}
public class CustomExceptionDemo {
    public static void main(String[] args) {
        try {
            test(22);
        } catch (CustomException e) {
     System.out.println("test方法报异常," +         e.getLocalizedMessage());
        }
    }

 private static void test(int age) throws CustomException {
        if (age == 22) {
            throw new CustomException("这是我的自定义异常");
        } else {
            System.out.println("不是自定义异常");
        }

   }
}

运行结果:

代码语言:javascript
代码运行次数:0
复制
test方法报异常,这是我的自定义异常

在工作中使用比较多的自定义方式,把上面的自定义进行改造:

代码语言:javascript
代码运行次数:0
复制
//自定义
public class CustomException extends Exception {
     //错误码
     private String errorCode;
     //错误信息
     private String errorMsg;

    public CustomException(String errorCode, String errorMsg) {
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }
   //省略调 get set toString
}
public class CustomExceptionDemo {
    public static void main(String[] args) {
        try {
            test(2);
        } catch (CustomException e) {
            System.out.println("test方法报异常,异常信息:" + e);
        }
    }
    private static void test(int age) throws CustomException {
        if (age == 2) {
            throw new CustomException("300001", "这是我的自定义异常");
        } else {
            System.out.println("不是自定义异常");
        }
    }
}

运行输出结果:

代码语言:javascript
代码运行次数:0
复制
test方法报异常,异常信息:CustomException{errorCode='300001', errorMsg='这是我的自定义异常'}

注意:异常堆栈信息,不是有多少就打多少,这方面也要悠着点,过多地打印错误日志也是会拖累系统的,能表达清楚就OK了。

异常就说到这里,期待下一期的异常面试题。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java后端技术栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 异常的分类
    • Error
    • Exception
      • checked异常还可以分为以下两类异常:
  • 异常关键字
    • 常见代码模板
  • 自定义异常
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档