8140281: add no-arg Optional.orElseThrow() as preferred alternative to get()

Reviewed-by: alanb, bpb, forax, darcy
This commit is contained in:
Stuart Marks 2017-12-13 18:47:20 -08:00
parent 0214135fde
commit feffd15dc2
8 changed files with 118 additions and 31 deletions

View file

@ -32,8 +32,9 @@ import java.util.stream.Stream;
/** /**
* A container object which may or may not contain a non-{@code null} value. * A container object which may or may not contain a non-{@code null} value.
* If a value is present, {@code isPresent()} returns {@code true} and * If a value is present, {@code isPresent()} returns {@code true}. If no
* {@code get()} returns the value. * value is present, the object is considered <i>empty</i> and
* {@code isPresent()} returns {@code false}.
* *
* <p>Additional methods that depend on the presence or absence of a contained * <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(Object) orElse()} * value are provided, such as {@link #orElse(Object) orElse()}
@ -137,14 +138,10 @@ public final class Optional<T> {
* {@code NoSuchElementException}. * {@code NoSuchElementException}.
* *
* @apiNote * @apiNote
* The methods {@link #orElse(Object) orElse} and * The preferred alternative to this method is {@link #orElseThrow()}.
* {@link #orElseGet(Supplier) orElseGet}
* are generally preferable to this method, as they return a substitute
* value if the value is absent, instead of throwing an exception.
* *
* @return the non-{@code null} value described by this {@code Optional} * @return the non-{@code null} value described by this {@code Optional}
* @throws NoSuchElementException if no value is present * @throws NoSuchElementException if no value is present
* @see Optional#isPresent()
*/ */
public T get() { public T get() {
if (value == null) { if (value == null) {
@ -361,6 +358,21 @@ public final class Optional<T> {
return value != null ? value : supplier.get(); return value != null ? value : supplier.get();
} }
/**
* If a value is present, returns the value, otherwise throws
* {@code NoSuchElementException}.
*
* @return the non-{@code null} value described by this {@code Optional}
* @throws NoSuchElementException if no value is present
* @since 10
*/
public T orElseThrow() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
/** /**
* If a value is present, returns the value, otherwise throws an exception * If a value is present, returns the value, otherwise throws an exception
* produced by the exception supplying function. * produced by the exception supplying function.

View file

@ -30,9 +30,10 @@ import java.util.function.Supplier;
import java.util.stream.DoubleStream; import java.util.stream.DoubleStream;
/** /**
* A container object which may or may not contain a {@code double} value. If a * A container object which may or may not contain a {@code double} value.
* value is present, {@code isPresent()} returns {@code true} and * If a value is present, {@code isPresent()} returns {@code true}. If no
* {@code getAsDouble()} returns the value. * value is present, the object is considered <i>empty</i> and
* {@code isPresent()} returns {@code false}.
* *
* <p>Additional methods that depend on the presence or absence of a contained * <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(double) orElse()} * value are provided, such as {@link #orElse(double) orElse()}
@ -117,14 +118,10 @@ public final class OptionalDouble {
* {@code NoSuchElementException}. * {@code NoSuchElementException}.
* *
* @apiNote * @apiNote
* The methods {@link #orElse(double) orElse} and * The preferred alternative to this method is {@link #orElseThrow()}.
* {@link #orElseGet(DoubleSupplier) orElseGet}
* are generally preferable to this method, as they return a substitute
* value if the value is absent, instead of throwing an exception.
* *
* @return the value described by this {@code OptionalDouble} * @return the value described by this {@code OptionalDouble}
* @throws NoSuchElementException if no value is present * @throws NoSuchElementException if no value is present
* @see OptionalDouble#isPresent()
*/ */
public double getAsDouble() { public double getAsDouble() {
if (!isPresent) { if (!isPresent) {
@ -225,6 +222,21 @@ public final class OptionalDouble {
return isPresent ? value : supplier.getAsDouble(); return isPresent ? value : supplier.getAsDouble();
} }
/**
* If a value is present, returns the value, otherwise throws
* {@code NoSuchElementException}.
*
* @return the value described by this {@code OptionalDouble}
* @throws NoSuchElementException if no value is present
* @since 10
*/
public double orElseThrow() {
if (!isPresent) {
throw new NoSuchElementException("No value present");
}
return value;
}
/** /**
* If a value is present, returns the value, otherwise throws an exception * If a value is present, returns the value, otherwise throws an exception
* produced by the exception supplying function. * produced by the exception supplying function.

View file

@ -30,9 +30,10 @@ import java.util.function.Supplier;
import java.util.stream.IntStream; import java.util.stream.IntStream;
/** /**
* A container object which may or may not contain an {@code int} value. If a * A container object which may or may not contain an {@code int} value.
* value is present, {@code isPresent()} returns {@code true} and * If a value is present, {@code isPresent()} returns {@code true}. If no
* {@code getAsInt()} returns the value. * value is present, the object is considered <i>empty</i> and
* {@code isPresent()} returns {@code false}.
* *
* <p>Additional methods that depend on the presence or absence of a contained * <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(int) orElse()} * value are provided, such as {@link #orElse(int) orElse()}
@ -117,14 +118,10 @@ public final class OptionalInt {
* {@code NoSuchElementException}. * {@code NoSuchElementException}.
* *
* @apiNote * @apiNote
* The methods {@link #orElse(int) orElse} and * The preferred alternative to this method is {@link #orElseThrow()}.
* {@link #orElseGet(IntSupplier) orElseGet}
* are generally preferable to this method, as they return a substitute
* value if the value is absent, instead of throwing an exception.
* *
* @return the value described by this {@code OptionalInt} * @return the value described by this {@code OptionalInt}
* @throws NoSuchElementException if no value is present * @throws NoSuchElementException if no value is present
* @see OptionalInt#isPresent()
*/ */
public int getAsInt() { public int getAsInt() {
if (!isPresent) { if (!isPresent) {
@ -224,6 +221,21 @@ public final class OptionalInt {
return isPresent ? value : supplier.getAsInt(); return isPresent ? value : supplier.getAsInt();
} }
/**
* If a value is present, returns the value, otherwise throws
* {@code NoSuchElementException}.
*
* @return the value described by this {@code OptionalInt}
* @throws NoSuchElementException if no value is present
* @since 10
*/
public int orElseThrow() {
if (!isPresent) {
throw new NoSuchElementException("No value present");
}
return value;
}
/** /**
* If a value is present, returns the value, otherwise throws an exception * If a value is present, returns the value, otherwise throws an exception
* produced by the exception supplying function. * produced by the exception supplying function.

View file

@ -30,9 +30,10 @@ import java.util.function.Supplier;
import java.util.stream.LongStream; import java.util.stream.LongStream;
/** /**
* A container object which may or may not contain a {@code long} value. If a * A container object which may or may not contain a {@code long} value.
* value is present, {@code isPresent()} returns {@code true} and * If a value is present, {@code isPresent()} returns {@code true}. If no
* {@code getAsLong()} returns the value. * value is present, the object is considered <i>empty</i> and
* {@code isPresent()} returns {@code false}.
* *
* <p>Additional methods that depend on the presence or absence of a contained * <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(long) orElse()} * value are provided, such as {@link #orElse(long) orElse()}
@ -117,14 +118,10 @@ public final class OptionalLong {
* {@code NoSuchElementException}. * {@code NoSuchElementException}.
* *
* @apiNote * @apiNote
* The methods {@link #orElse(long) orElse} and * The preferred alternative to this method is {@link #orElseThrow()}.
* {@link #orElseGet(LongSupplier) orElseGet}
* are generally preferable to this method, as they return a substitute
* value if the value is absent, instead of throwing an exception.
* *
* @return the value described by this {@code OptionalLong} * @return the value described by this {@code OptionalLong}
* @throws NoSuchElementException if no value is present * @throws NoSuchElementException if no value is present
* @see OptionalLong#isPresent()
*/ */
public long getAsLong() { public long getAsLong() {
if (!isPresent) { if (!isPresent) {
@ -224,6 +221,21 @@ public final class OptionalLong {
return isPresent ? value : supplier.getAsLong(); return isPresent ? value : supplier.getAsLong();
} }
/**
* If a value is present, returns the value, otherwise throws
* {@code NoSuchElementException}.
*
* @return the value described by this {@code OptionalLong}
* @throws NoSuchElementException if no value is present
* @since 10
*/
public long orElseThrow() {
if (!isPresent) {
throw new NoSuchElementException("No value present");
}
return value;
}
/** /**
* If a value is present, returns the value, otherwise throws an exception * If a value is present, returns the value, otherwise throws an exception
* produced by the exception supplying function. * produced by the exception supplying function.

View file

@ -132,6 +132,13 @@ public class Basic {
Boolean got = empty.orElseThrow(ObscureException::new); Boolean got = empty.orElseThrow(ObscureException::new);
} }
@Test(expectedExceptions=NoSuchElementException.class)
public void testEmptyOrElseThrowNoArg() throws Exception {
Optional<Boolean> empty = Optional.empty();
Boolean got = empty.orElseThrow();
}
@Test(groups = "unit") @Test(groups = "unit")
public void testPresent() { public void testPresent() {
Optional<Boolean> empty = Optional.empty(); Optional<Boolean> empty = Optional.empty();
@ -147,6 +154,7 @@ public class Basic {
assertTrue(!present.toString().equals(presentEmptyString.toString())); assertTrue(!present.toString().equals(presentEmptyString.toString()));
assertTrue(-1 != present.toString().indexOf(Boolean.TRUE.toString())); assertTrue(-1 != present.toString().indexOf(Boolean.TRUE.toString()));
assertSame(Boolean.TRUE, present.get()); assertSame(Boolean.TRUE, present.get());
assertSame(Boolean.TRUE, present.orElseThrow());
AtomicBoolean presentCheck = new AtomicBoolean(); AtomicBoolean presentCheck = new AtomicBoolean();
present.ifPresent(v -> presentCheck.set(true)); present.ifPresent(v -> presentCheck.set(true));
@ -191,6 +199,7 @@ public class Basic {
instance = Optional.ofNullable("Duke"); instance = Optional.ofNullable("Duke");
assertTrue(instance.isPresent()); assertTrue(instance.isPresent());
assertEquals(instance.get(), "Duke"); assertEquals(instance.get(), "Duke");
assertEquals(instance.orElseThrow(), "Duke");
} }
@Test(groups = "unit") @Test(groups = "unit")
@ -214,11 +223,13 @@ public class Basic {
result = duke.filter(s -> s.startsWith("D")); result = duke.filter(s -> s.startsWith("D"));
assertTrue(result.isPresent()); assertTrue(result.isPresent());
assertEquals(result.get(), "Duke"); assertEquals(result.get(), "Duke");
assertEquals(result.orElseThrow(), "Duke");
Optional<String> emptyString = Optional.of(""); Optional<String> emptyString = Optional.of("");
result = emptyString.filter(String::isEmpty); result = emptyString.filter(String::isEmpty);
assertTrue(result.isPresent()); assertTrue(result.isPresent());
assertEquals(result.get(), ""); assertEquals(result.get(), "");
assertEquals(result.orElseThrow(), "");
} }
@Test(groups = "unit") @Test(groups = "unit")
@ -287,6 +298,7 @@ public class Basic {
l = duke.flatMap(s -> Optional.of(s.length())); l = duke.flatMap(s -> Optional.of(s.length()));
assertTrue(l.isPresent()); assertTrue(l.isPresent());
assertEquals(l.get().intValue(), 4); assertEquals(l.get().intValue(), 4);
assertEquals(l.orElseThrow().intValue(), 4);
// Verify same instance // Verify same instance
l = duke.flatMap(s -> fixture); l = duke.flatMap(s -> fixture);

View file

@ -124,6 +124,13 @@ public class BasicDouble {
double got = empty.orElseThrow(ObscureException::new); double got = empty.orElseThrow(ObscureException::new);
} }
@Test(expectedExceptions=NoSuchElementException.class)
public void testEmptyOrElseThrowNoArg() throws Exception {
OptionalDouble empty = OptionalDouble.empty();
double got = empty.orElseThrow();
}
@Test(groups = "unit") @Test(groups = "unit")
public void testPresent() { public void testPresent() {
OptionalDouble empty = OptionalDouble.empty(); OptionalDouble empty = OptionalDouble.empty();
@ -137,7 +144,9 @@ public class BasicDouble {
assertTrue(Double.hashCode(1.0) == present.hashCode()); assertTrue(Double.hashCode(1.0) == present.hashCode());
assertFalse(present.toString().isEmpty()); assertFalse(present.toString().isEmpty());
assertTrue(-1 != present.toString().indexOf(Double.toString(present.getAsDouble()).toString())); assertTrue(-1 != present.toString().indexOf(Double.toString(present.getAsDouble()).toString()));
assertTrue(-1 != present.toString().indexOf(Double.toString(present.orElseThrow()).toString()));
assertEquals(1.0, present.getAsDouble()); assertEquals(1.0, present.getAsDouble());
assertEquals(1.0, present.orElseThrow());
AtomicBoolean presentCheck = new AtomicBoolean(); AtomicBoolean presentCheck = new AtomicBoolean();
present.ifPresent(v -> presentCheck.set(true)); present.ifPresent(v -> presentCheck.set(true));

View file

@ -124,6 +124,13 @@ public class BasicInt {
int got = empty.orElseThrow(ObscureException::new); int got = empty.orElseThrow(ObscureException::new);
} }
@Test(expectedExceptions=NoSuchElementException.class)
public void testEmptyOrElseThrowNoArg() throws Exception {
OptionalInt empty = OptionalInt.empty();
int got = empty.orElseThrow();
}
@Test(groups = "unit") @Test(groups = "unit")
public void testPresent() { public void testPresent() {
OptionalInt empty = OptionalInt.empty(); OptionalInt empty = OptionalInt.empty();
@ -137,7 +144,9 @@ public class BasicInt {
assertTrue(Integer.hashCode(1) == present.hashCode()); assertTrue(Integer.hashCode(1) == present.hashCode());
assertFalse(present.toString().isEmpty()); assertFalse(present.toString().isEmpty());
assertTrue(-1 != present.toString().indexOf(Integer.toString(present.getAsInt()).toString())); assertTrue(-1 != present.toString().indexOf(Integer.toString(present.getAsInt()).toString()));
assertTrue(-1 != present.toString().indexOf(Integer.toString(present.orElseThrow()).toString()));
assertEquals(1, present.getAsInt()); assertEquals(1, present.getAsInt());
assertEquals(1, present.orElseThrow());
AtomicBoolean presentCheck = new AtomicBoolean(); AtomicBoolean presentCheck = new AtomicBoolean();
present.ifPresent(v -> presentCheck.set(true)); present.ifPresent(v -> presentCheck.set(true));

View file

@ -124,6 +124,13 @@ public class BasicLong {
long got = empty.orElseThrow(ObscureException::new); long got = empty.orElseThrow(ObscureException::new);
} }
@Test(expectedExceptions=NoSuchElementException.class)
public void testEmptyOrElseThrowNoArg() throws Exception {
OptionalLong empty = OptionalLong.empty();
long got = empty.orElseThrow();
}
@Test(groups = "unit") @Test(groups = "unit")
public void testPresent() { public void testPresent() {
OptionalLong empty = OptionalLong.empty(); OptionalLong empty = OptionalLong.empty();
@ -137,7 +144,9 @@ public class BasicLong {
assertTrue(Long.hashCode(1) == present.hashCode()); assertTrue(Long.hashCode(1) == present.hashCode());
assertFalse(present.toString().isEmpty()); assertFalse(present.toString().isEmpty());
assertTrue(-1 != present.toString().indexOf(Long.toString(present.getAsLong()).toString())); assertTrue(-1 != present.toString().indexOf(Long.toString(present.getAsLong()).toString()));
assertTrue(-1 != present.toString().indexOf(Long.toString(present.orElseThrow()).toString()));
assertEquals(1L, present.getAsLong()); assertEquals(1L, present.getAsLong());
assertEquals(1L, present.orElseThrow());
AtomicBoolean presentCheck = new AtomicBoolean(); AtomicBoolean presentCheck = new AtomicBoolean();
present.ifPresent(v -> presentCheck.set(true)); present.ifPresent(v -> presentCheck.set(true));