Class Iterables.LazyReference<T>

  • Type Parameters:
    T - the type of the contained element.
    All Implemented Interfaces:
    java.util.function.Supplier<T>
    Direct Known Subclasses:
    Iterables.Memoizer.Lazy
    Enclosing class:
    Iterables

    abstract static class Iterables.LazyReference<T>
    extends java.lang.ref.WeakReference<T>
    implements java.util.function.Supplier<T>
    Class supports the implementation of Iterables.memoize(Iterable) and is not intended for general use. Lazily loaded reference that is not constructed until required. This class is used to maintain a reference to an object that is expensive to create and must be constructed once and once only. This reference behaves as though the final keyword has been used (you cannot reset it once it has been constructed). Object creation is guaranteed to be thread-safe and the first thread that calls get() will be the one that creates it.

    Usage: clients need to implement the create() method to return the object this reference will hold.

    For instance:

     final LazyReference<MyObject> ref = new LazyReference() {
       protected MyObject create() throws Exception {
         // Do expensive object construction here
         return new MyObject();
       }
     };
     
    Then call get() to get a reference to the referenced object:
     MyObject myLazyLoadedObject = ref.get()
     
    NOTE: Interruption policy is that if you want to be cancellable while waiting for another thread to create the value, instead of calling get() call getInterruptibly(). However, If your create() method is interrupted and throws an InterruptedException, it is treated as an application exception and will be the causal exception inside the runtime Iterables.LazyReference.InitializationException that get() or getInterruptibly() throws and your create() will not be called again.

    This class is NOT Serializable.

    Implementation note. This class extends WeakReference as Reference does not have a public constructor. WeakReference is preferable as it does not have any members and therefore doesn't increase the memory footprint. As we never pass a referent through to the super-class and override get(), the garbage collection semantics of WeakReference are irrelevant. The referenced object will not become eligible for GC unless the object holding the reference to this object is collectible.

    • Constructor Detail

      • LazyReference

        public LazyReference()
    • Method Detail

      • create

        protected abstract T create()
                             throws java.lang.Exception
        The object factory method, guaranteed to be called once and only once.
        Returns:
        the object that get() and getInterruptibly() will return.
        Throws:
        java.lang.Exception - if anything goes wrong, rethrown as an InitializationException from get() and getInterruptibly()
      • get

        public final T get()
        Get the lazily loaded reference in a non-cancellable manner. If your create() method throws an Exception calls to get() will throw an InitializationException which wraps the previously thrown exception.
        Specified by:
        get in interface java.util.function.Supplier<T>
        Overrides:
        get in class java.lang.ref.Reference<T>
        Returns:
        the object that create() created.
        Throws:
        Iterables.LazyReference.InitializationException - if the create() method throws an exception. The Throwable.getCause() will contain the exception thrown by the create() method
      • getInterruptibly

        public final T getInterruptibly()
                                 throws java.lang.InterruptedException
        Get the lazily loaded reference in a cancellable manner. If your create() method throws an Exception, calls to get() will throw a RuntimeException which wraps the previously thrown exception.
        Returns:
        the object that create() created.
        Throws:
        Iterables.LazyReference.InitializationException - if the create() method throws an exception. The Throwable.getCause() will contain the exception thrown by the create() method
        java.lang.InterruptedException - If the calling thread is Interrupted while waiting for another thread to create the value (if the creating thread is interrupted while blocking on something, the InterruptedException will be thrown as the causal exception of the Iterables.LazyReference.InitializationException to everybody calling this method).
      • isInitialized

        public final boolean isInitialized()
        Has the create() reference been initialized.
        Returns:
        true if the task is complete
      • cancel

        public final void cancel()
        Cancel the initializing operation if it has not already run. Will try and interrupt if it is currently running.