使用Java8的新特性 Optional 代替 if - else 解决空指针问题
静态构造方法
JDK提供三个静态方法来构造一个`Optional`
-
public
final
class
Optional<T> {
-
-
private
static
final Optional<?> EMPTY =
new
Optional<>();
-
private
final T value;
-
-
// 该方法用来构造一个空的 Optional,如果 Optional 中的 value 为 null 则该 Optional 为不包含值的状态
-
public
static<T> Optional<T>
empty
() {
-
@SuppressWarnings("unchecked")
-
Optional<T> t = (Optional<T>) EMPTY;
-
return t;
-
}
-
-
// 通过一个非 null 的 value 来构造一个 Optional,
-
// 返回的 Optional 包含了 value 这个值。对于该方法,传入的参数一定不能为 null,否则便会抛出 NullPointerException
-
public
static <T> Optional<T>
of
(T value) {
-
return
new
Optional<>(value);
-
}
-
-
// 该方法和 of 方法的区别在于,传入的参数可以为 null,如果为 null 的话,返回的就是 Optional.empty()
-
public
static <T> Optional<T>
ofNullable
(T value) {
-
return value ==
null ? empty() : of(value);
-
}
-
}
常用方法
isPresent() / ifPresent()
-
// 如果值存在返回true,否则返回false
-
public
boolean
isPresent
() {
-
return value !=
null;
-
}
-
-
// 如果Optional实例有值则为其调用consumer ,否则不做处理。
-
public
void
ifPresent
(Consumer<? super T> consumer) {
-
if (value !=
null)
-
consumer.accept(value);
-
}
测试
-
public
class
OptionalTest {
-
public
static
void
main
(String[] args) {
-
User
user
=
new
User();
-
Optional<User> optional = Optional.ofNullable(user);
-
optional.ifPresent(s -> System.out.println(s));
-
}
-
}
Get()
获取Optional中的值,这个值也就是我们的值,Optional相当于就是一个外壳。
-
public T
get
() {
-
if (value ==
null) {
-
throw
new
NoSuchElementException(
"No value present");
-
}
-
return value;
-
}
orElse() / orElseGet() / orElseThrow()
-
// 如果Optional中的值不为空,则返回Optional中的值,如果为空,则返回other值,
-
public T
orElse
(T other) {
-
return value !=
null ? value : other;
-
}
-
-
// 如果Optional中存在值,则返回值,否则返回other调用的结果
-
public T
orElseGet
(Supplier<? extends T> other) {
-
return value !=
null ? value : other.get();
-
}
-
-
// 如果Optional中的值存在,则返回值,值不存在,则抛出异常函数Supplier中的异常
-
public <X
extends
Throwable> T
orElseThrow
(Supplier<? extends X> exceptionSupplier)
throws X {
-
if (value !=
null) {
-
return value;
-
}
else {
-
throw exceptionSupplier.get();
-
}
-
}
测试
-
String
value
=
"2";
-
String
orElse
= Optional.ofNullable(value).orElse(
"1");
-
System.out.println(orElse);
//2
-
-
String
value
=
null;
-
String
orElse
= Optional.ofNullable(value).orElse(
"1");
-
System.out.println(orElse);
//1
-
-
-------------------------------------------------------
-
-
public
class
OptionalTest {
-
public
static
void
main
(String[] args) {
-
String
value
=
null;
-
String
orElse
= Optional.ofNullable(value).orElseGet(OptionalTest::get);
-
System.out.println(orElse);
// 123
-
-
String
value
=
"2";
-
String
orElse
= Optional.ofNullable(value).orElseGet(OptionalTest::get);
-
System.out.println(orElse);
// 2
-
}
-
-
public
static String
get
(){
-
return
"123";
-
}
-
}
-
-
-------------------------------------------------------
-
-
public
class
OptionalTest {
-
public
static
void
main
(String[] args) {
-
String
value
=
null;
-
String
orElse
= Optional.ofNullable(value).orElseThrow(() ->
new
RuntimeException(
"不存在值"));
-
System.out.println(orElse);
-
}
-
}
map() / flatMap()
-
map(Function)
:如果 Optional 不为空,应用 Function 于 Optional 中的内容,并返回结果。否则直接返回 Optional.empty。 -
flatMap(Function)
:同map()
,但是提供的映射函数将结果包装在 Optional 对象中,因此flatMap()
不会在最后进行任何包装。
以上方法都不适用于数值型 Optional。一般来说,流的 filter()
会在 Predicate 返回 false
时移除流元素。而 Optional.filter()
在失败时不会删除 Optional,而是将其保留下来,并转化为空。
-
// 将Optional中的值作为参数传递到map中,如果传入的值为空,则返回一空的Optional对象,相当于Optional.empty(),
-
// 如果不为空,我们可以返回一个可以描述描述结果的返回值(Optional中的值,这个值可以重新赋值)
-
public<U> Optional<U>
map
(Function<? super T, ? extends U> mapper) {
-
Objects.requireNonNull(mapper);
-
if (!isPresent())
-
return empty();
-
else {
-
return Optional.ofNullable(mapper.apply(value));
-
}
-
}
-
-
// 如果Optional中值存在,那么返回一个基于Optional的值(如Optional),
-
// 如果Optional中的值不存在,则返回一空的Optional对象,相当于Optional.empty(),
-
// 与map不同, map返回的是一个值,而flatMap返回一个基于Optional的值
-
public<U> Optional<U>
flatMap
(Function<? super T, Optional<U>> mapper) {
-
Objects.requireNonNull(mapper);
-
if (!isPresent())
-
return empty();
-
else {
-
return Objects.requireNonNull(mapper.apply(value));
-
}
-
}
测试
-
public
class
OptionalTest {
-
public
static
void
main
(String[] args) {
-
User
user
=
null;
-
Optional<String> optional = Optional.ofNullable(user).map(OptionalTest::getMap);
-
System.out.println(optional);
//Optional.empty
-
-
User
user
=
new
User();
-
user.setUsername(
"Admin");
-
Optional<String> optional = Optional.ofNullable(user).map(OptionalTest::getMap);
-
System.out.println(optional);
// Optional[Admin]
-
-
}
-
-
public
static String
getMap
(User user){
-
return user.getUsername();
-
}
-
-
-------------------------------------------------------
-
-
User
user
=
new
User();
-
user.setUsername(
"Admin");
-
Optional<String> optional = Optional.ofNullable(user).flatMap(OptionalTest::getFlatMap);
-
System.out.println(optional);
-
}
-
public
static Optional<String>
getFlatMap
(User user){
-
return Optional.ofNullable(user).map(User::getUsername);
-
}
-
filter()
将Optional中的值作为参数传入,如果符合规则,那么返回一个Optional对象,否则返回一个空的Optional 对象(Optional.empty)
-
public Optional<T>
filter
(Predicate<? super T> predicate) {
-
Objects.requireNonNull(predicate);
-
if (!isPresent())
-
return
this;
-
else
-
return predicate.test(value) ?
this : empty();
-
}
实战
ifPresent(),这是一个终端操作,如果value存在则会调用指定的消费方法
-
// 获取 book 的值,若 book 为 null 则返回默认值
-
String
book
= Optional.ofNullable(person).map(Person::getBook).orElse(
"default");
-
-
// person 不为 null 则打印薪水
-
Optional.ofNullable(person).ifPresent(p -> System.out.println(p.getSalary()));
-
-
// 若 book 为 null,则设置默认值
-
Optional.ofNullable(person)
-
.map(Person::getComputer)
-
.ifPresent(c -> c.setBrandName(
"default name"));
-
-
Optional.ofNullable(person)
-
.map(Person::getComputer)
-
.ifPresent(
this::consumerTest);
-
-
public
void
consumerTest
(Computer computer){
-
System.out.println(
"consumer test");
-
System.out.println(computer);
-
}
-
-
// 获取brand,若 brandName 为 "",则抛出异常
-
// 因为 map只能过滤掉 null 值,而在工作中通常还需要做其它的判断,所以我们可以使用 map 去解析实体类中的某个属性,然后使用 filter 进行对应的过滤
-
String
brand
= Optional.ofNullable(person)
-
.map(Person::getComputer)
-
.map(Computer::getBrandName)
-
.filter(b -> !b.equals(
""))
-
.orElseThrow(() ->
new
NumberFormatException(
"品牌为空"));
-
System.out.println(
"brand: " + brand);