Lazy field initialization with lambdas

后端 未结 14 2270
日久生厌
日久生厌 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

    It's supported,

    By creating a small interface and combining 2 new features introduced in java 8:

    • @FunctionalInterface annotation (allows assigning a lambda on declaration)
    • default keyword (define an implementation, just like abstract class - but in an interface)

    It is possible to get the same Lazy behavior as you seen in C#.


    Usage

    Lazy name = () -> "Java 8";
    System.out.println(name.get());
    

    Lazy.java (copy and paste this interface in somewhere accessible)

    import java.util.function.Supplier;
    
    @FunctionalInterface
    public interface Lazy extends Supplier {
        abstract class Cache {
            private volatile static Map instances = new HashMap<>();
    
            private static synchronized Object getInstance(int instanceId, Supplier create) {
    
                Object instance = instances.get(instanceId);
                if (instance == null) {
                    synchronized (Cache.class) {
                        instance = instances.get(instanceId);
                        if (instance == null) {
                            instance = create.get();
                            instances.put(instanceId, instance);
                        }
                    }
                }
                return instance;
            }
        }
    
        @Override
        default T get() {
            return (T) Cache.getInstance(this.hashCode(), () -> init());
        }
    
        T init();
    }
    
    

    Online Example - https://ideone.com/3b9alx

    The following snippet demonstrates the lifecycle of this helper class

    static Lazy name1 = () -> { 
        System.out.println("lazy init 1"); 
        return "name 1";
    };
        
    static Lazy name2 = () -> { 
        System.out.println("lazy init 2"); 
        return "name 2";
    };
    
    public static void main (String[] args) throws java.lang.Exception
    {
        System.out.println("start"); 
        System.out.println(name1.get());
        System.out.println(name1.get());
        System.out.println(name2.get());
        System.out.println(name2.get());
        System.out.println("end"); 
    }
    

    will output

    start
    lazy init 1
    name 1
    name 1
    lazy init 2
    name 2
    name 2
    end
    

    See the online demo - https://ideone.com/3b9alx

    提交回复
    热议问题