重构orElseThrow块返回RuntimeException时遇类型匹配错误求助
解决orElseThrow()调用void方法时的"no instance of type variable exists so that void conforms"错误
这个问题我碰到过好几次了,核心原因是你没搞清楚orElseThrow()参数的函数式接口要求!
错误原因拆解
orElseThrow()方法需要接收一个**Supplier<Throwable>**类型的参数——简单说,这个参数必须是一个能返回异常实例的"供给型"函数,它的抽象方法get()要求返回一个Throwable子类对象,而不能是void类型的方法。
你现在写的throwBadRequestException()是void方法(直接抛出异常,没有返回值),当你把它直接传给orElseThrow()时,编译器发现它不符合Supplier的返回值要求,所以抛出了这个类型不匹配的错误。
两种可行的解决方案
方案1:把异常方法改成返回异常实例的方法(推荐)
把throwBadRequestException()改成返回BadRequestException对象的方法,这样就能直接用方法引用或者lambda表达式传给orElseThrow():
// 重构后的异常方法:返回异常实例,而不是直接抛出 private BadRequestException throwBadRequestException() { return new BadRequestException("未找到符合价格范围的商品"); } // 在findProductBetweenPriceRange中调用 public Product findProductBetweenPriceRange(int minPrice, int maxPrice) { return productRepository.findByPriceBetween(minPrice, maxPrice) // 用方法引用直接传递,简洁明了 .orElseThrow(this::throwBadRequestException); }
如果需要动态传递错误信息,还可以给异常方法加参数:
private BadRequestException throwBadRequestException(String message) { return new BadRequestException(message); } public Product findProductBetweenPriceRange(int minPrice, int maxPrice) { String errorMsg = String.format("未找到价格在%d到%d之间的商品", minPrice, maxPrice); return productRepository.findByPriceBetween(minPrice, maxPrice) .orElseThrow(() -> throwBadRequestException(errorMsg)); }
方案2:用Lambda包裹void类型的异常方法(不推荐,仅作参考)
如果你坚持要保留void类型的异常方法(直接在方法内抛出异常),可以用Lambda表达式把它包裹起来,同时补上一个无意义的return null来满足Supplier的返回值要求:
// 原void类型的异常方法 private void throwBadRequestException() { throw new BadRequestException("未找到符合价格范围的商品"); } public Product findProductBetweenPriceRange(int minPrice, int maxPrice) { return productRepository.findByPriceBetween(minPrice, maxPrice) .orElseThrow(() -> { throwBadRequestException(); // 这里的return null永远不会执行,只是为了满足编译器对Supplier返回值的要求 return null; }); }
这种方式虽然能解决错误,但代码不够优雅,而且容易让人困惑,所以更推荐第一种方案。
内容的提问来源于stack exchange,提问作者Vasu
相关产品推荐
相关产品推荐

