将 java.util.function.Function 定义为 static final

Dis*_*ana 2 java static java-8 functional-interface

在我的代码中,我们必须将欧元转换为欧分:将 aBigDecimal作为输入,我们必须将其乘以 100。

我们需要多次应用这种转换,所以我们决定使用UnaryOperatorfrom java.util.function

private static final UnaryOperator<BigDecimal> CONVERT_EURO_TO_CENTS =
        input -> input.multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.DOWN);
Run Code Online (Sandbox Code Playgroud)

然后我们使用CONVERT_EURO_TO_CENTS如下:

[.....]

    CONVERT_EURO_TO_CENT.apply(<aBigDecimal>)

[.....]
Run Code Online (Sandbox Code Playgroud)

将 声明UnaryOperator为常量 ( static final)可能是危险的,以避免多线程环境中的数据不一致(线程安全)?

Nat*_*hes 9

不,这并不危险。

如果你创建一个可变对象并将它放在一个静态字段中,那么不同的线程可能会改变它的状态并导致麻烦。

虽然这里的静态 final 字段持有对 lambda 的引用,但没有什么是可变的。它没有任何可以被多个线程篡改的状态。BigDecimal 上的每个操作都是线程安全的,BigDecimal 是不可变的。即使 BigDecimal 不是线程安全的,其他线程也无法访问传递给 lambda 的参数。

顺便说一句,如果您使用局部变量实现 lambda,那仍然是线程安全的,唯一的状态仅限于执行该方法的堆栈帧。

考虑一下您是否要将这个 lambda 放入一个变量中并在不同的地方使用它,您不妨使用静态方法。你没有得到任何使它成为 lambda 的东西。如果您需要将它作为参数传递,您仍然可以使用方法引用来做到这一点。

  • 作为旁注,在参考实现中,“input -&gt; input.multiply(BigDecimal.valueOf(100)) .setScale(0, RoundingMode.DOWN)”无论如何都会计算为共享单例,即使您不存储它在“静态最终”字段中。因此,在多个线程中使用它是安全的,但由于无论如何都会发生,因此没有必要将其存储在字段中(除非不使用字段会导致同一 lambda 表达式多次出现)。 (5认同)
  • @GovindaSakare 该对象是无状态的,这就是它可以安全共享的原因。这发生在参考实现中(来自 Oracle 的 OpenJDK 和 Java 8)。请参阅[lambda 表达式每次执行时都会在堆上创建对象吗?](/sf/ask/1926711181/) (3认同)