diff --git a/android/guava-tests/test/com/google/common/base/SuppliersTest.java b/android/guava-tests/test/com/google/common/base/SuppliersTest.java index 282dd568fa41..5de3395ed092 100644 --- a/android/guava-tests/test/com/google/common/base/SuppliersTest.java +++ b/android/guava-tests/test/com/google/common/base/SuppliersTest.java @@ -81,12 +81,12 @@ static class SerializableThrowingSupplier extends ThrowingSupplier implements Se static void checkMemoize(CountingSupplier countingSupplier, Supplier memoizedSupplier) { // the underlying supplier hasn't executed yet assertEquals(0, countingSupplier.calls); - + assertFalse(memoizedSupplier.isInitialized()); assertEquals(10, (int) memoizedSupplier.get()); // now it has assertEquals(1, countingSupplier.calls); - + assertTrue(memoizedSupplier.isInitialized()); assertEquals(10, (int) memoizedSupplier.get()); // it still should only have executed once due to memoization @@ -165,7 +165,7 @@ public void testMemoizeSerializable() throws Exception { Object unused2 = memoizedSupplier.get(); CountingSupplier countingCopy = - (CountingSupplier) ((Suppliers.MemoizingSupplier) copy).delegate; + (CountingSupplier) ((Suppliers.SerializableMemoizingSupplier) copy).delegate; checkMemoize(countingCopy, copy); } diff --git a/android/guava/src/com/google/common/base/Suppliers.java b/android/guava/src/com/google/common/base/Suppliers.java index 9476c21872fc..05e36144d3e9 100644 --- a/android/guava/src/com/google/common/base/Suppliers.java +++ b/android/guava/src/com/google/common/base/Suppliers.java @@ -110,18 +110,34 @@ public String toString() { *

If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is * returned directly. */ - public static Supplier memoize(Supplier delegate) { + public static MemoizingSupplier memoize(Supplier delegate) { if (delegate instanceof NonSerializableMemoizingSupplier - || delegate instanceof MemoizingSupplier) { - return delegate; + || delegate instanceof SerializableMemoizingSupplier) { + return (MemoizingSupplier) delegate; } return delegate instanceof Serializable - ? new MemoizingSupplier(delegate) + ? new SerializableMemoizingSupplier(delegate) : new NonSerializableMemoizingSupplier(delegate); } + /** + * A supplier that memoizes the result of the first call to {@link #get()} and returns the same + * result on subsequent calls to {@link #get()}. + * + * @author Alexey Pelykh + */ + @ElementTypesAreNonnullByDefault + public interface MemoizingSupplier extends Supplier { + /** + * Returns {@code true} if the supplier has been initialized, i.e. if the first call to + * {@link #get()} has been made or if the supplier has been explicitly initialized. + */ + boolean isInitialized(); + } + @VisibleForTesting - static class MemoizingSupplier implements Supplier, Serializable { + static class SerializableMemoizingSupplier + implements MemoizingSupplier, Serializable { private transient Object lock = new Object(); final Supplier delegate; @@ -130,7 +146,7 @@ static class MemoizingSupplier implements Supplier delegate) { + SerializableMemoizingSupplier(Supplier delegate) { this.delegate = checkNotNull(delegate); } @@ -154,6 +170,11 @@ public T get() { return uncheckedCastNullableTToT(value); } + @Override + public boolean isInitialized() { + return initialized; + } + @Override public String toString() { return "Suppliers.memoize(" @@ -172,7 +193,8 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE } @VisibleForTesting - static class NonSerializableMemoizingSupplier implements Supplier { + static class NonSerializableMemoizingSupplier + implements MemoizingSupplier { private final Object lock = new Object(); @SuppressWarnings("UnnecessaryLambda") // Must be a fixed singleton object @@ -208,6 +230,11 @@ public T get() { return uncheckedCastNullableTToT(value); } + @Override + public boolean isInitialized() { + return delegate == SUCCESSFULLY_COMPUTED; + } + @Override public String toString() { Supplier delegate = this.delegate; diff --git a/guava-tests/test/com/google/common/base/SuppliersTest.java b/guava-tests/test/com/google/common/base/SuppliersTest.java index 282dd568fa41..5de3395ed092 100644 --- a/guava-tests/test/com/google/common/base/SuppliersTest.java +++ b/guava-tests/test/com/google/common/base/SuppliersTest.java @@ -81,12 +81,12 @@ static class SerializableThrowingSupplier extends ThrowingSupplier implements Se static void checkMemoize(CountingSupplier countingSupplier, Supplier memoizedSupplier) { // the underlying supplier hasn't executed yet assertEquals(0, countingSupplier.calls); - + assertFalse(memoizedSupplier.isInitialized()); assertEquals(10, (int) memoizedSupplier.get()); // now it has assertEquals(1, countingSupplier.calls); - + assertTrue(memoizedSupplier.isInitialized()); assertEquals(10, (int) memoizedSupplier.get()); // it still should only have executed once due to memoization @@ -165,7 +165,7 @@ public void testMemoizeSerializable() throws Exception { Object unused2 = memoizedSupplier.get(); CountingSupplier countingCopy = - (CountingSupplier) ((Suppliers.MemoizingSupplier) copy).delegate; + (CountingSupplier) ((Suppliers.SerializableMemoizingSupplier) copy).delegate; checkMemoize(countingCopy, copy); } diff --git a/guava/src/com/google/common/base/Suppliers.java b/guava/src/com/google/common/base/Suppliers.java index 9476c21872fc..05e36144d3e9 100644 --- a/guava/src/com/google/common/base/Suppliers.java +++ b/guava/src/com/google/common/base/Suppliers.java @@ -110,18 +110,34 @@ public String toString() { *

If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is * returned directly. */ - public static Supplier memoize(Supplier delegate) { + public static MemoizingSupplier memoize(Supplier delegate) { if (delegate instanceof NonSerializableMemoizingSupplier - || delegate instanceof MemoizingSupplier) { - return delegate; + || delegate instanceof SerializableMemoizingSupplier) { + return (MemoizingSupplier) delegate; } return delegate instanceof Serializable - ? new MemoizingSupplier(delegate) + ? new SerializableMemoizingSupplier(delegate) : new NonSerializableMemoizingSupplier(delegate); } + /** + * A supplier that memoizes the result of the first call to {@link #get()} and returns the same + * result on subsequent calls to {@link #get()}. + * + * @author Alexey Pelykh + */ + @ElementTypesAreNonnullByDefault + public interface MemoizingSupplier extends Supplier { + /** + * Returns {@code true} if the supplier has been initialized, i.e. if the first call to + * {@link #get()} has been made or if the supplier has been explicitly initialized. + */ + boolean isInitialized(); + } + @VisibleForTesting - static class MemoizingSupplier implements Supplier, Serializable { + static class SerializableMemoizingSupplier + implements MemoizingSupplier, Serializable { private transient Object lock = new Object(); final Supplier delegate; @@ -130,7 +146,7 @@ static class MemoizingSupplier implements Supplier delegate) { + SerializableMemoizingSupplier(Supplier delegate) { this.delegate = checkNotNull(delegate); } @@ -154,6 +170,11 @@ public T get() { return uncheckedCastNullableTToT(value); } + @Override + public boolean isInitialized() { + return initialized; + } + @Override public String toString() { return "Suppliers.memoize(" @@ -172,7 +193,8 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE } @VisibleForTesting - static class NonSerializableMemoizingSupplier implements Supplier { + static class NonSerializableMemoizingSupplier + implements MemoizingSupplier { private final Object lock = new Object(); @SuppressWarnings("UnnecessaryLambda") // Must be a fixed singleton object @@ -208,6 +230,11 @@ public T get() { return uncheckedCastNullableTToT(value); } + @Override + public boolean isInitialized() { + return delegate == SUCCESSFULLY_COMPUTED; + } + @Override public String toString() { Supplier delegate = this.delegate;