super(msg)层层上抛
super(msg)
就是“把构造参数 msg 原封不动地交给父类的构造器”。
在继承体系里,子类构造器 必须 先帮父类完成初始化;super(...)
就是干这件事的桥梁。
下面用“登录失败”这个场景,把它拆成 4 层,让你一眼看到 super(msg)
到底把 msg 送到哪、最后怎么用。
- 最底层:JDK 自带的 RuntimeException
package java.lang;public class RuntimeException extends Exception {// 留意这个字段private String detailMessage;public RuntimeException(String message) {// 再交给 Exceptionsuper(message);}public String getMessage() {return detailMessage;}
}
- 真正把
message
保存到字段detailMessage
的是Exception
的构造器; - 之后任何地方都可以
e.getMessage()
取出来。
- 你们项目封装的 BaseException
package com.sky.exception;public class BaseException extends RuntimeException {// 可以扩展错误码、国际化 key 等字段public BaseException(String msg) {// 关键点:把 msg 继续往上传给 RuntimeExceptionsuper(msg);}
}
- 这里如果省略
super(msg)
,编译器会 隐式调用父类的无参构造器super()
;
而RuntimeException
没有无参构造就报错,所以必须显式写super(msg)
。 - 以后想加错误码,只要在
BaseException
再写一个字段即可,不影响子类。
- 业务异常 LoginFailedException(你现在看到的类)
public class LoginFailedException extends BaseException {public LoginFailedException(String msg){super(msg); // 把 msg 再交给 BaseException}
}
- 这一层就是 纯转发,没有额外逻辑,但起到了“语义化”作用:
让代码里看到LoginFailedException
就知道这是“登录失败”而不是别的业务错误。
- 最终使用:全局异常处理器
@ExceptionHandler(LoginFailedException.class)
public Result<Void> handle(LoginFailedException e){log.warn("登录失败:{}", e.getMessage()); // 这里取出的就是原来 super(msg) 传进来的字符串return Result.error(e.getMessage());
}
一句话总结
super(msg)
就是“把当前这一层收到的 msg
继续往上抛”,
最终落到 JDK 的 Exception.detailMessage
字段里,
使得任何 catch
到它的地方都能用 e.getMessage()
拿到“用户名或密码错误”这类业务提示。