将java.util.function.Function定义为staticfinal

在我的代码中,我们必须将欧元转换为欧分:将 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);

然后我们使用CONVERT_EURO_TO_CENTS如下:

[.....]

    CONVERT_EURO_TO_CENT.apply(<aBigDecimal>)

[.....]

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

回答

不,这并不危险。

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

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

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

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

  • As a side note, in the reference implementation, `input -> input.multiply(BigDecimal.valueOf(100)) .setScale(0, RoundingMode.DOWN)` evaluates to a shared singleton anyway, even if you don’t store it in a `static final` field. So, using it with multiple threads is safe, but since it happens anyway, storing it in a field is unnecessary (unless not using a field would lead to multiple occurrences of the same lambda expression).
  • @GovindaSakhare the object is stateless, which is the reason why it can be shared safely. Which happens in the reference implementation (OpenJDK and Java 8 from Oracle). See [Does a lambda expression create an object on the heap every time it's executed?](https://stackoverflow.com/q/27524445/2711488)

以上是将java.util.function.Function定义为staticfinal的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>