Lazy field initialization with lambdas

后端 未结 14 2304
日久生厌
日久生厌 2020-11-29 23:39

I would like to implement lazy field initialization (or deferred initialization) without an if statement and taking advantage of lambdas. So, I would like to have the same b

14条回答
  •  日久生厌
    2020-11-30 00:05

    Well, I don't really suggest having no "if", but here's my take on the matter:

    One simple method is to use an AtomicReference (the ternary operator is still like an "if"):

    private final AtomicReference lazyVal = new AtomicReference<>();
    
    void foo(){
        final Something value = lazyVal.updateAndGet(x -> x != null ? x : expensiveCreate());
        //...
    }
    

    But then there is the whole thread safety magic that one might not need. So I'd do it like Miguel with a little twist:

    Since I like simple one-liners, I simply use a ternary operator (again, reads like an "if") but I'd let Java's evaluation order do its magic to set the field:

    public static  Supplier lazily(final Supplier supplier) {
        return new Supplier() {
            private T value;
    
            @Override
            public T get() {
                return value != null ? value : (value = supplier.get());
            }
        };
    }
    

    gerardw's field-modification example above, that works without an "if", can be further simplified too. We don't need the interface. We just need to exploit above "trick" again: An assignment operator's result is the assigned value, we can use brackets to force evaluation order. So with the method above it's just:

    static  Supplier value(final T value) {
       return () -> value;
    }
    
    
    Supplier p2 = () -> (p2 = value(new Point())).get();
    

    Note that you cannot inline the "value(...)" method without losing the laziness.

提交回复
热议问题