Java中的异常

Java中的异常

1、Java异常类层次结构图

在这里插入图片描述

Java中的异常是指一个在程序执行期间发生的事件,它中断正在执行程序的正常指令流,为了能够及时有效地处理程序中的运行错误,必须使用异常类。

在Java中,所有的异常都有一个共同的祖先,就是java.lang包下的Throwable类 。Throwable类有两个重要的子类:

  • Exception:程序本身可以处理的异常,可以通过catch来进行捕获。Exception可以分为Checked Exception(受检查异常,必须处理)和 Unchecked Exception(不受检查异常,可以不处理)
  • Error:Error属于程序无法处理的错误,不建议通过catch捕获。例如 Java虚拟机运行错误、虚拟机内存不够错误、类定义错误等 。这些异常发生时,Java虚拟机一般会选择线程终止

2、Checked Exception 和 Unchecked Exception有什么区别?

Checked Exception 即受检查异常。也叫作编译时异常

Java代码在编译过程中,如果受检查异常没有被catch或者throws关键字处理的话,就没办法通过编译。

在这里插入图片描述

像这样,IDEA会提示去try…catch或者throws出去。

除了RuntimeException及其子类以外,其他的Exception类及其子类都属于受检查异常 。常见的受检查异常有:IO相关的异常、ClassNotFoundException、SQLException

Unchecked Exception 即不受检查异常。也叫做运行时异常

Java代码在编译过程中,我们即使不处理不受检查异常也可以正常通过编译。

RuntimeException及其子类都统称为非受检查异常,常见的有:

  • NullPointerException(空指针异常)
  • IllegalArgumentException(参数错误比如方法入参类型错误)
  • NumberFormatException(字符串转换为数字格式错误,IllegalArgumentException的子类)
  • ArrayIndexOutOfBoundsException (数组越界错误)
  • ClassCastException(类型转换错误)
  • ArithmeticException(安全错误比如权限不够)
  • UnsupportedOperationException(不支持的操作错误比如重复创建同一用户)

3、Throwable类常用方法有哪些

  • String getMessage():返回异常发生时的简要描述
  • String toString():返回异常发生时的详细信息
  • String getLocalizedMessage():返回异常对象的本地化信息。
  • void printStackTrace():在控制台上打印Throwable对象封装的异常信息

4、try-catch-finally如何使用?

  • try块:用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块
  • catch块:用于处理try捕获到的异常
  • finally块:无论是否捕获或处理异常,finally块里的语句都会被执行 。当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行
try {
    System.out.println("Try to do something");
    throw new RuntimeException("RuntimeException");
} catch (Exception e) {
    System.out.println("Catch Exception -> " + e.getMessage());
} finally {
    System.out.println("Finally");
}

不要在finally语句块中使用return 。当try语句和finally语句中都有return语句时,try语句块中的return语句会被忽略。这是因为,try语句中的return返回值会先被暂存在一个本地变量中,当执行到finally语句中的return之后,这个本地变量的值就变为了finally语句中的return返回值

5、finally中的代码一定会执行吗?

不一定。在某些特殊情况下,finally中的代码不会被执行

  • finally之前虚拟机被终止运行的话,finally中的代码不会被执行
  • 程序所在的线程死亡
  • 关闭CPU

6、异常使用有哪些需要注意的?

  • 不要把异常定义为静态变量,这样会导致异常栈信息错乱。每次手动抛出异常,我们都需要手动new一个异常对象抛出
  • 抛出的异常信息一定要有意义
  • 建议抛出更加具体的异常比如:字符串转换为数字格式错误的时候应该抛出NumberFormatException而不是其父类IllegalArgumentException

抛出更具体的异常是为了提供更多的关于问题的信息,帮助程序员更快地定位和解决问题 。抛出更具体的异常是良好的编程实践之一,可提高代码的可读性、可维护性和可靠性。

  • 使用日志打印异常之后就不要再抛出异常了(两者不要同时存在一段代码逻辑中)

自定义异常

1、自定义异常

虽然Java中有很多异常类,但是在实际开发中所遇到的一些异常,不能完全表示。这时候就需要我们自定义异常类

  • 定义一个取款超出余额时的异常
/**
 * 自定义异常,取款超出余额时抛出异常
 */
public class AccountOverDrawnException extends Exception{
    public AccountOverDrawnException() {
        super();
    }

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

    @Override
    public String toString(){
        return getMessage();
    }
}
  • 在使用到的类中捕获这个异常
   if (money > balance) {
            try{
                throw new AccountOverDrawnException("取款失败,账户余额不足");
            }catch (AccountOverDrawnException e){
                e.printStackTrace();
            }
        } else if (money < 0) {
            System.out.println("取款失败,取款金额小于0");
        } else {
            //进行取款
     ...
   }
}

2、SpringBoot中全局异常处理

创建一个全局异常管理

创建GlobalExceptionHandle.java

package com.xqh.exception;
import com.xqh.common.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@Slf4j
@RestControllerAdvice   //捕获全局异常
public class GlobalExceptionHandler {
   
  	@ExceptionHandler(ServiceException.class)
    @ResponseBody
    public Result handle(ServiceException se){
        return Result.error(se.getCode(),se.getMessage());
    }

    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    @ExceptionHandler(value = ShiroException.class)
    public Result handler(ShiroException e) {
        log.error("运行时异常:----------------{}", e);
        return Result.fail(401, e.getMessage(), null);
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result handler(MethodArgumentNotValidException e) {
        log.error("实体校验异常:----------------{}", e);
        BindingResult bindingResult = e.getBindingResult();
        ObjectError objectError = bindingResult.getAllErrors().stream().findFirst().get();
        return Result.fail(objectError.getDefaultMessage());
    }
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = IllegalArgumentException.class)
    public Result handler(IllegalArgumentException e) {
        log.error("Assert异常:----------------{}", e);
        return Result.fail(e.getMessage());
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = RuntimeException.class)
    public Result handler(RuntimeException e) {
        log.error("运行时异常:----------------{}", e);
        return Result.fail(e.getMessage());
    }



}


上面我们捕捉了几个异常:

  • ServiceException: Service层抛出的异常

  • ShiroException:shiro 抛出的异常,比如没有权限,用户登录异常

  • IllegalArgumentException:处理 Assert 的异常

  • MethodArgumentNotValidException:处理实体校验的异常

  • RuntimeException:捕捉其他异常 运行时的异常

定义每一个异常类

如ServiceException.java


@Getter
public class ServiceException extends RuntimeException {
    private String code;
    public ServiceException(String code,String msg){
        super(msg);
        this.code=code;
    }

}


使用全局异常类

 //登录
    public UserDTO login(UserDTO userDTO) {
        User one = getUserInfo(userDTO);
        if (one !=null){
           BeanUtil.copyProperties(one,userDTO,true);
           return userDTO;
       }else {
           throw new ServiceException(Constants.CODE_600,"用户名或密码错误");  //抛出异常
       }


    }

这样就完成了全局异常的处理。只要有需要自定义的异常,写出异常类,然后注册到GlobalExceptionHandle中。然后就可以全局使用这些异常了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java异常机制是一种用于处理程序执行期间可能出现的错误情况的机制。Java异常分为两类:受检异常(Checked Exception)和非受检异常(Unchecked Exception)。其,受检异常必须在代码进行捕获和处理,否则编译器将会报错。而非受检异常则不需要在代码进行捕获和处理,但是如果不进行处理,会导致程序的异常终止。 Java异常机制通过抛出异常对象来表示程序出现的异常情况,通常情况下,异常对象包含了异常的类型、异常的消息以及异常发生的位置等信息。当程序执行过程出现异常情况时,就会抛出相应的异常对象,这个异常对象会被传递给调用栈上的上层方法,直到被捕获或者到达程序的顶层方法。 Java异常机制主要由三个关键字来实现:try、catch和finally。try块包含可能抛出异常的代码,catch块用于捕获并处理异常,finally块则用于执行一些必须要完成的代码,无论是否抛出异常都会执行。 下面是一个简单的Java异常处理的例子: ``` public class ExceptionDemo { public static void main(String[] args) { try { int num = Integer.parseInt(args[0]); System.out.println("10 / " + num + " = " + (10 / num)); } catch (ArithmeticException e) { System.out.println("除数不能为0"); } catch (NumberFormatException e) { System.out.println("请输入数字"); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("请至少输入一个参数"); } finally { System.out.println("程序执行完毕"); } } } ``` 在这个例子,我们使用了try-catch-finally关键字来处理用户输入的参数,当输入参数不满足条件时,就会抛出相应的异常。catch块用于捕获并处理异常,finally块则用于执行一些必须要完成的代码,无论是否抛出异常都会执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zero摄氏度

感谢鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值