【问题标题】:error: incompatible types: unexpected return value : Java 8 [duplicate]错误:不兼容的类型:意外的返回值:Java 8 [重复]
【发布时间】:2019-04-28 02:05:15
【问题描述】:

我编写了一个返回布尔值的简单方法。

private boolean isActionAvailable(Collection<StudentConfiguration> studentConfigs){
       if(studentConfigs != null)
        {
            studentConfigs.forEach(studentConfig -> {
                if(studentConfig.action() == null || !studentConfig.action().equals(Action.DELETE)) {
                    return true;
                }
            });
        }
        return false;
    }

该方法抛出以下异常。

error: incompatible types: unexpected return value
            studentConfigs.forEach(studentConfig -> 

我的代码有什么问题?

【问题讨论】:

    标签: java foreach java-8 java-stream


    【解决方案1】:

    我不建议你在这里使用 Stream API。看看foreach这个版本是多么的清晰简洁:

    private boolean isActionAvailable(Collection<StudentConfiguration> studentConfigurations) {
        if(studentConfigurations == null) {
            return false;
        }
    
        for (StudentConfiguration configuration : studentConfigurations) {
            if (!Action.DELETE.equals(configuration.action())) {
                return true;
            }
        }
    
        return false;
    }
    

    否则,如果你是一个狂热的人,

    private boolean isActionAvailable(Collection<StudentConfiguration> configs) {
        return configs != null &&
               configs.stream()
                      .map(StudentConfiguration::action)
                      .anyMatch(Predicate.isEqual​(Action.DELETE).negate()));
    }
    

    【讨论】:

      【解决方案2】:

      这是 forEach() 方法 forEach(Consumer&lt;? super T&gt; action) 的签名。
      它引用了具有方法void accept(T t) 的消费者接口。 在您的代码中,您将覆盖 accept() 并返回一个无效的值,因为 accept() 具有 void 返回类型。
      因此它显示错误

       error: incompatible types: unexpected return value
                  studentConfigs.forEach(studentConfig ->
      

      【讨论】:

        【解决方案3】:

        传递给forEach 的 lambda 表达式不应有返回值。

        如果输入 Collection 的任何元素满足条件,您似乎想要返回 true

        private boolean isActionAvailable(Collection<StudentConfiguration> studentConfigs){
            if(studentConfigs != null) {
                if (studentConfigs.stream().anyMatch(sc -> sc.action() == null || !sc.action().equals(Action.DELETE))) {
                    return true;
                }
            }
            return false;
        }
        

        正如 Holger 所建议的,这可以简化为一条语句:

        return studentConfigs != null && studentConfigs.stream().anyMatch(sc -> sc.action() == null || !sc.action().equals(Action.DELETE));
        

        return studentConfigs != null ? studentConfigs.stream().anyMatch(sc -> sc.action() == null || !sc.action().equals(Action.DELETE)) : false;
        

        【讨论】:

        • 为什么不做一个简单的增强型forloop?你什么时候选择一个而不是另一个?
        • @LukeGarrigan 增强的 for 循环也可以。至于选择哪一个,我会选择对您(以及可能阅读您的代码的其他开发人员)更易读的一个。我认为在这个例子中使用anyMatch 更好地表达了该方法正在做什么,即查找输入集合的任何元素是否满足某些条件。
        • @LukeGarrigan Java 是一种不断发展的语言。高阶函数正在发挥作用。我建议你接受它们,而不是落伍
        • @LukeGarrigan “我想这只是因为我没有尽可能频繁地使用它。”是的,差不多。这是 Java 的未来,因此您只会看到越来越多的这些高阶函数。
        • @LukeGarrigan 好吧,你会使用collection.contains(obj) 而不是循环遍历集合来测试每个元素是否相等,不是吗?所以collection.stream().anyMatch(condition) 只是这个想法的概括,当条件比简单的相等更复杂时。
        【解决方案4】:

        您的 lambda 中的 return 语句将终止该 lambda,而不是 isActionAvailable() 方法。因此,推断的 lambda 类型现在是错误的,因为 forEach 需要 Consumer

        查看其他答案以了解如何解决该问题。

        【讨论】:

          【解决方案5】:

          也可以使用 Java9 及更高版本,您可以使用 Stream.ofNullable 并更新为:

          private boolean isActionAvailable(Collection<StudentConfiguration> studentConfigs) {
              return Stream.ofNullable(studentConfigs)
                      .flatMap(Collection::stream)
                      .anyMatch(studentConfig -> studentConfig.action() == null || !studentConfig.action().equals(Action.DELETE));
          }
          

          【讨论】:

          • Stream.ofNullable(studentConfigs) .flatMap(Collection::stream) … 是否比studentConfigs != null &amp;&amp; studentConfigs.stream() … 更简单值得商榷
          • @Holger By simpler 你是指可读性方面还是性能方面?可读性我相信是基于意见的,我发现现在很容易阅读,也许有时我不会有。
          • 当我写评论时,我的意思只是可读性,但现在你要问了……flatMap 存在缺乏惰性的问题,这在 Java 9 中仍然存在,这将是一个在 Java 10 之前不使用您的变体的理由。但在最近的版本中,我不会考虑任何剩余的微小性能差异。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-26
          • 2016-09-11
          • 1970-01-01
          • 2021-04-15
          • 1970-01-01
          • 2015-02-15
          相关资源
          最近更新 更多