java - IntelliJ - 方法引用可能会改变语义

标签 java intellij-idea lambda

我有以下代码:

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

看来roleName -> roleService.findRoleByName(roleName)可以替换为方法引用(即对特定对象的实例方法的引用),但是 IntelliJ IDEA 警告说这可能会改变语义:

screenshot

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

最佳答案

如果您不遵循干净函数式编程的规则,则在将 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)。

关于java - IntelliJ - 方法引用可能会改变语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61283367/

相关文章:

java - 获取 java JRE 的路径

java - 示例类(class)代码未编译

java - 是否有在 IntelliJ 中使用 system.out.println 包装语句的快捷方式

java - IntelliJ 中的源步骤后 Log4j 消息对象意外呈现

java - 错误 :(42, 70) java : underscores in literals are not supported in -source 1. 6(使用 -source 7 或更高版本在文字中启用下划线)

python - 了解 python 中的嵌套 lambda 函数行为

c++ - 为 lambda 分配名称会影响性能吗?

java - svnkit 错误 :org. tmatesoft.svn.core.SVNException: svn: E175002: 连接被服务器拒绝

java - 为什么没有显示实际的 Switch 图像/动画?

c++ - 在通用 lambda 中使用模板参数