重写父类异常处理方法时ResponseEntity泛型返回值编译错误如何解决
问题原因
这是Java协变返回类型和泛型不变性共同作用的结果:
- 普通类的协变规则:Java 5及以上版本支持协变返回类型,子类重写父类方法时,返回值类型可以是父类方法返回值类型的子类。你第一个
globalException方法,父类返回ErrorResponse,子类返回它的子类ErrorResponseWrapper,完全符合协变规则,因此编译正常。 - 泛型的不变性:Java泛型不支持协变,也就是说哪怕
ErrorResponseWrapper是ErrorResponse的子类,ResponseEntity<ErrorResponseWrapper>也不属于ResponseEntity<ErrorResponse>的子类。你第二个方法父类返回ResponseEntity<ErrorResponse>,子类尝试返回ResponseEntity<ErrorResponseWrapper>,不符合协变返回类型要求,因此触发编译不兼容错误。
解决方案
提供3种可落地的方案,按需选择即可:
方案1:保持方法重写,调整子类返回值声明
最简单的改法,不需要修改父类代码:把子类方法的返回值改回父类声明的ResponseEntity<ErrorResponse>,实际返回的实例还是ErrorResponseWrapper即可。JSON序列化会按实际实例类型输出字段,不会丢失新增的type属性:
@Override public ResponseEntity<ErrorResponse> customException(CustomException ex) { ErrorResponse parentResult = super.customException(ex).getBody(); // 注意你原代码里的ResponseWrapper是笔误,应该是ErrorResponseWrapper ErrorResponseWrapper wrapper = new ErrorResponseWrapper(); wrapper.setType("SOMETHING"); // 记得把父类返回的其他属性赋值到wrapper中 wrapper.setErrorDescription(parentResult.getErrorDescription()); wrapper.setErrorMessage(parentResult.getErrorMessage()); return new ResponseEntity<>(wrapper, ex.getStatus()); }
方案2:修改父类方法的泛型声明
如果可以调整公共父类的代码,给父类返回值加上泛型上界通配符,支持所有子类的协变返回:
// 父类GlobalExceptionHandler中的方法调整 public ResponseEntity<? extends ErrorResponse> customException(CustomException ex) { // 原有逻辑不变 }
调整后子类直接返回ResponseEntity<ErrorResponseWrapper>也符合重写规则,不会报错。
方案3:不使用重写,直接在子类定义独立的异常处理方法
如果父类不可修改,也不想调整返回值,直接去掉@Override注解,给子类的方法加上@ExceptionHandler注解即可。Spring异常处理会优先匹配当前类中声明的异常处理方法,等效于覆盖父类逻辑,没有编译问题:
@ExceptionHandler(value = CustomException.class) public ResponseEntity<ErrorResponseWrapper> customException(CustomException ex) { // 原有逻辑不变 }
内容的提问来源于stack exchange,提问作者ima.technophyle
相关产品推荐
相关产品推荐

