Java常用类:异常看这篇就够了

作为一个稀有的Java妹子,所写的所有博客都只是当作自己的笔记,留下证据自己之前是有用心学习的~哈哈哈哈(如果有不对的地方,也请大家指出,不要悄悄咪咪的不告诉我)

Throwable,Exception,Error关系

Java中的异常机制可以便于开发人员定位程序中的错误,那么如何优雅的抛出异常呢?首先要清楚Java中的异常类,以及它们之间的关系。
在这里插入图片描述
异常主要分为两大类:Exception和Error,两个都继承Throwable类

public class Throwable implements Serializable
public class Error extends Throwable
public class Exception extends Throwable

Exception

Exception类是开发中经常会使用到的类,分为编译时异常和运行时异常。
编译时异常指:程序员在撸代码时,就要处理的异常,编译软件会以红色波浪线提示此处的代码需要手动抛出异常,不然编译不会通过;

File file = new File("/User/DownLoad/1.txt");
//这里就会爆红,只是我复制出来,不在idea中,看不到红色波浪线
FileInputStream io = new FileInputStream(file);
常见编译时异常抛出原因
FileNotFoundException文件有可能不存在,就会抛出此异常
ClassNotFoundException找不到具体指定类的定义

运行时异常指:在运行时才能发现的异常,编译期无法判断代码是否会有异常,也就是大家耳熟能详的bug,基本上都是运行时异常,因为编译期的异常只要不是红绿色盲基本上都能够try catch或是throw掉。

常见运行时异常抛出原因
NullPointerException空指针
ArrayIndexOutOfBoundsException数组下标越界

Error

Error一般是系统级别的,由Java虚拟机生成并抛出,程序内部无法捕获。常见的Error主要由程序进入死循环,内存泄露,栈溢出等等,这类异常只能通过分析代码,找出原因并优化代码。

如何捕获异常

1.try catch finally

当知道哪段代码会抛异常,或者有编译时异常时,通常我们会使用try catch finally来处理异常,这三个关键字不能单独出现,可以try…catch,try…finally,try…catch…finally,当然如果有多个异常的话,catch可以有多个(注意catch的顺序应该是子类在前,父类在后,因为当catch块有多个时,异常匹配到其中一个程序就停止了)。
finally是不管有没有抛异常都会执行的代码块,一般会把释放连接、释放锁等操作放在该代码块中,不建议在finally中使用return,这样就覆盖try和catch中的return,除非你想返回的结果就是finally中的。

		try{
            int i= 1/0;
        }catch (ArithmeticException e1){
            System.out.println("除数不能是0");
        }
        catch (Exception e){
            System.out.println(e);
        }finally {
            System.out.println("finally");
        }

结果:

除数不能是0
finally

2. throw

如果在当前方法中我们并不想处理这个异常,那么就把异常抛出,让调用方法者处理异常,在mvc中,往上抛到controller层就不能继续抛出了,需要使用try…catch捕获异常,封装异常信息返回前端。

/*
编译时异常通过在方法后面throws关键字,将异常往上抛出,
调用该方法的处理异常
*/
public static void test() throws FileNotFoundException {
        File file = new File("/User/Download/1.txt");
        FileInputStream io = new FileInputStream(file);
        
    }
public static void main(String[] args) {
        try {
        	/*因为test会抛出异常,那么就需要处理,从这里也可以推测
        	编译时异常方法,就是在方法中把异常抛出来,我们在使用
        	的时候就必须处理,要么继续往上抛,要么try...catch*/
            test();
        } catch (FileNotFoundException e) {
            System.out.println("文件不存在!!");
        }
    }
/*字节流的源码,可以看到该方法会抛出异常,所以在调用该方法时我们需要手动
处理异常
*/
public FileInputStream(File file) throws FileNotFoundException {
        String name = (file != null ? file.getPath() : null);
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(name);
        }
        if (name == null) {
            throw new NullPointerException();
        }
        if (file.isInvalid()) {
            throw new FileNotFoundException("Invalid file path");
        }
        fd = new FileDescriptor();
        fd.attach(this);
        path = name;
        open(name);
    }

3.自定义异常

有些业务层面的异常,比如用户信息不存在,该用户身份不能进行此操作等等。这类信息其实不算严格意义上的异常,只是不满足业务要求,像这类信息我们可以通过自定义异常来处理。

public class MyException extends Exception {
    public MyException() {
        super();
    }
    
    public MyException(String message){
        super(message);
    }

    

    public MyException(String message, Throwable cause) {
        super(message, cause);
    }



    public MyException(Throwable cause) {
        super(cause);
    }

    protected MyException(String message, Throwable cause,
                        boolean enableSuppression,
                        boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}
//一般将异常信息定义为枚举
public enum MyExceptionEnum {
    USER_NOT_EXIST(201,"用户不存在");
    private Integer code;
    private String msg;
    MyExceptionEnum(Integer code,String msg){
        this.code = code;
        this.msg = msg;
    }

    public Integer getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }
}

public static void test() throws MyException {
        UserDO userDO = userMapper.selectByPrimaryKey(1);
        if(userDO ==null){
        	/*当用户不存在时,就抛出自定义异常,然后在controller层
        	捕获,返回错误信息给前端
        	*/
            throw new MyException(MyExceptionEnum.USER_NOT_EXIST.getMsg());
        }
    }

4.Springmvc全局异常

Spring有一个全局异常处理器ExceptionHandler,只要在controller层将异常声明为全局异常,在service层抛出的全局异常,不需要在controller层显式的使用try…catch捕获,springmvc会自动封装model返回给前端。
需要注意的是自定义异常需要继承的是RuntimeException

public class MyException extends RuntimeException {
    public MyException() {
        super();
    }

    public MyException(String message){
        super(message);
    }



    public MyException(String message, Throwable cause) {
        super(message, cause);
    }



    public MyException(Throwable cause) {
        super(cause);
    }

    protected MyException(String message, Throwable cause,
                        boolean enableSuppression,
                        boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }

}

枚举类的定义不变,抛出的方式也不变,不过需要新增一个类定义全局异常

@RestControllerAdvice(annotations = RestController.class)
@Slf4j
public class ControllerExceptionHandleAdvice {
    
    @ExceptionHandler(MyException.class)
    public ResultVO myExceptionHandler(HttpServletResponse response,
                                         MyException e) {
        log.error("dubbo业务处理异常 {}", e.getMessage(), e);
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        return ResultVO.fail(e.getMessage());
    }
}

这样定义以后,controller就不要捕获异常,在哪里抛出就直接返回给前端

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值