使用Optional调用私有方法遇编译错误,求正确代码实现方案
嘿,我来帮你捋清楚这个问题~你原本想用Optional替代繁琐的空检查,思路是对的,但在API的使用上有点小偏差,咱们一步步拆解:
先看你的原代码和改写后的问题
你原本的空检查逻辑是没问题的:
final OrderLines orderLines = readFromMockFile(); if (null != searchCriteria.getSearch() && StringUtils.isNotEmpty(searchCriteria.getSearch().getValue())) { applySearchConfig(searchCriteria.getSearch(), orderLines); }
这段代码的意图很明确:当searchCriteria.getSearch()不为空,且它的getValue()也非空时,调用私有方法applySearchConfig()。
但改成Optional写法后出现了编译错误:
Optional.ofNullable(searchCriteria.getSearch()) .map(x -> StringUtils.isNotEmpty(x.getValue())) .ifPresent(applySearchConfig(searchCriteria.getSearch()));
错误提示:The method ifPresent(Consumer) in the type Optional is not applicable for the arguments (OrderLines)
错误原因拆解
map()用错了方向:你用map()把Search对象转换成了一个Boolean值(也就是StringUtils.isNotEmpty(x.getValue())的结果),这时候Optional里包裹的已经不是原来的Search对象,而是Boolean类型了。ifPresent()的参数完全不符合要求:ifPresent()需要的是一个Consumer函数式接口——简单说就是一个「接收参数但没有返回值」的lambda表达式。但你直接写applySearchConfig(searchCriteria.getSearch()),这相当于立刻执行了这个方法,还把它的返回值(看起来是OrderLines类型)传给了ifPresent(),这肯定不匹配呀!
正确的改写方式
我们要保持Optional里的Search对象,同时过滤出符合「getValue()非空」条件的实例,再执行方法,这里有两种靠谱的写法:
写法一:用filter()过滤条件(最推荐)
final OrderLines orderLines = readFromMockFile(); Optional.ofNullable(searchCriteria.getSearch()) .filter(x -> StringUtils.isNotEmpty(x.getValue())) // 只保留满足条件的Search对象 .ifPresent(search -> applySearchConfig(search, orderLines)); // 存在时执行方法
这里filter()会筛选出符合条件的Search对象,只有当Optional里有这个对象时,ifPresent()里的lambda才会执行,lambda直接用筛选后的search对象调用方法,既安全又简洁。
写法二:嵌套Optional处理getValue()(更严谨的链式调用)
如果想把getValue()的空检查也用Optional链式处理,可以这样写:
final OrderLines orderLines = readFromMockFile(); Optional.ofNullable(searchCriteria.getSearch()) .map(Search::getValue) // 提取getValue()的结果,转成Optional<String> .filter(StringUtils::isNotEmpty) // 过滤非空的字符串 .ifPresent(value -> applySearchConfig(searchCriteria.getSearch(), orderLines));
不过要注意:这种写法里,如果你在ifPresent()里再次调用searchCriteria.getSearch(),要确保这个值不会在中间被修改,否则可能出现空值风险,所以第一种写法其实更稳妥。
小提醒
ifPresent()的核心是当Optional存在有效内容时,执行一个「消费」该内容的操作,所以一定要传lambda表达式(比如search -> doSomething(search)),而不是直接执行方法哦!
内容的提问来源于stack exchange,提问作者Abhishek Galoda

