Intellij Idea IntelliJ -方法引用可能会更改语义

gcxthw6b  于 2023-10-15  发布在  其他
关注(0)|答案(1)|浏览(113)

我有以下代码:

return userService.getAll()
    .stream()
    .map(User::getRoleName)
    .map(roleName -> roleService.findRoleByName(roleName))
    .collect(Collectors.toSet());

似乎roleName -> roleService.findRoleByName(roleName)可以被方法引用(即 * 对特定对象的示例方法的引用 *)取代,但IntelliJ IDEA警告说这可能会改变语义:

它如何改变语义?它会改变语义吗?

r7xajy2e

r7xajy2e1#

如果你不遵循干净的函数式编程的规则,当你将lambda转换为方法引用时,可能会有语义上的变化。
不同之处在于,方法引用仅在构建流时解析一次。但是在lambda表达式中,获取方法的代码可以在lambda的每次执行中进行评估。
下面是一个简短的自包含示例用于演示:

public class Test40 {
  public static void main(String[] args) {
    Function<Integer, Integer> f2 = n -> 2 * n;
    Function<Integer, Integer> f3 = n -> 3 * n;
    Function<Integer, Integer>[] funcArray = new Function[1];

    funcArray[0] = f2;
    Stream.of(1, 2, 3)
          .peek(n -> { if (n > 1) funcArray[0] = f3; })
          .map(funcArray[0]::apply)            // Method reference, '::apply' could be omitted
          .forEach(System.out::print);         // prints 246
    System.out.println();

    funcArray[0] = f2;
    Stream.of(1, 2, 3)
          .peek(n -> { if (n > 1) funcArray[0] = f3; })
          .map(n -> funcArray[0].apply(n))     // Lambda
          .forEach(System.out::print);         // prints 269
    System.out.println();
  }
}

如何避免这个问题:使用流时不要使用副作用。不要使用peek进行处理!这个方法的存在主要是为了支持调试(看看javadoc)。

相关问题