2

In my code we have to convert euros into euro cents: taken a BigDecimal as input we have to multiply it by 100.

We need to apply this conversion a lot of times, so we decided to use an UnaryOperator from java.util.function:

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

Then we used the CONVERT_EURO_TO_CENTS as follows:

[.....]

    CONVERT_EURO_TO_CENT.apply(<aBigDecimal>)

[.....]

Could be dangerous declaring the UnaryOperator as a constant (static final), avoiding data inconsistency in a multi-threaded environment (thread safety)?

harry-potter
  • 1,981
  • 5
  • 29
  • 55

1 Answers1

9

No, this isn’t dangerous.

If you make a mutable object and put it in a static field then different threads can change its state and cause trouble.

Here though the static final field holds a reference to a lambda, and nothing there is mutable. It doesn’t have any state that multiple threads can tamper with. Each operation on BigDecimal is thread-safe, BigDecimal is immutable. Even if BigDecimal wasn’t threadsafe other threads wouldn’t have access to the argument passed into the lambda.

Btw if you implement the lambda with local variables, that’s still thread-safe, the only state is confined to the stack frame executing the method.

Consider if you’re going to put this lambda in a variable and use it in different places you might as well use a static method. You’re not gaining anything making this a lambda. If you need to pass it as an argument you can still do that using a method reference.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • 5
    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). – Holger Apr 08 '21 at 11:56
  • @Holger `evaluates to a shared singleton anyway` didn't get it. As per my understanding, it's but an implementation Functional Interface that would be stateless. – Govinda Sakhare Apr 08 '21 at 12:07
  • 3
    @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) – Holger Apr 08 '21 at 12:11
  • @Holger Thanks pal, much helpful. – Govinda Sakhare Apr 08 '21 at 12:22