java中怎么改变白天模式,如何防止或避免NPE地狱 !

提到过一点"防止NPE,是程序员的基本修养

NPE:Null Pointer Exception, 可能是基本上是最常见的一种异常类型, 同时也是最容易忽视的异常! 实际开发中,这个问题很容易就可以发生, 一发生可能就得重新打包上线(比较常见的几个行为: 强制转换, 数据库查询返回null, Session取数据)

举例 代码

//此时如果user 为 null, 则出 空指针异常

user.getArea().getName();

改进

//但是这种写法并不优雅(if 地狱),为了避免这种情况, Java8 提供了Optional类!

if(user != null){

user.getArea().getName();

}

解析

1. Optional(T value),empty(),of(T value),ofNullable(T value)

of(T value)

Optional(T value)是private权限, 不可外部调用.其余为public权限.故其本质为内部存储了一个真实的值, 在构造期间直接判断是否为空. 创建Optional对象,差别在于of不允许参数是null,而ofNullable则无限制。[下图源码: 摘自网络]

1d3da9e74b2ad8969187726eb6a53526.png

//of(T value) 源码

/**

* Returns an {@code Optional} with the specified present non-null value.

*

* @param the class of the value

* @param value the value to be present, which must be non-null

* @return an {@code Optional} with the value present

* @throws NullPointerException if value is null

*/

public static Optional of(T value) {

return new Optional<>(value);

}

也就是说of(T value)函数内部调用了构造函数。根据构造函数的源码我们可以得出两个结论:

通过of(T value)函数所构造出的Optional对象,当Value值为空时,依然会报NullPointerException。

通过of(T value)函数所构造出的Optional对象,当Value值不为空时,能正常构造Optional对象。

除此之外呢,Optional类内部还维护一个value为null的对象,大概就是长下面这样的

/**

* Constructs an empty instance.

*

* @implNote Generally only one empty instance, {@link Optional#EMPTY},

* should exist per VM.

*/

private Optional() {

this.value = null;

}

/**

* Returns an empty {@code Optional} instance. No value is present for this

* Optional.

*

* @apiNote Though it may be tempting to do so, avoid testing if an object

* is empty by comparing with {@code ==} against instances returned by

* {@code Option.empty()}. There is no guarantee that it is a singleton.

* Instead, use {@link #isPresent()}.

*

* @param Type of the non-existent value

* @return an empty {@code Optional}

*/

public static Optional empty() {

@SuppressWarnings("unchecked")

Optional t = (Optional) EMPTY;

return t;

}

所以: empty()的作用就是返回EMPTY对象。

ofNullable(T value)作用

源码:

/**

* Returns an {@code Optional} describing the specified value, if non-null,

* otherwise returns an empty {@code Optional}.

*

* @param the class of the value

* @param value the possibly-null value to describe

* @return an {@code Optional} with a present value if the specified value

* is non-null, otherwise an empty {@code Optional}

*/

public static Optional ofNullable(T value) {

return value == null ? empty() : of(value);

}

相比较of(T value)的区别就是,当value值为null时,of(T value)会报NullPointerException异常;ofNullable(T value)不会throw Exception,ofNullable(T value)直接返回一个EMPTY对象。

2.orElse(T other),orElseGet(Supplier extends T> other)和orElseThrow(Supplier extends X> exceptionSupplier)

这三个函数放一组进行记忆,都是在构造函数传入的value值为null时,进行调用的。orElse和orElseGet的用法如下所示,相当于value值为null时,给予一个默认值:

//这两个函数的区别:

//当user值不为null时,orElse函数依然会执行createUser()方法,而orElseGet函数并不会执行createUser()方法

//至于orElseThrow,就是value值为null时,直接抛一个异常出去,用法如下所示

@Test

public void test() {

User user = null;

user = Optional. ofNullable (user) .orElse (createUser() ) ;

user = Optional. ofNullable (user) .orElseGet( () -> createUser() ) ;

}

public User createUser() {

User user = new User();

user.setName("jianglong") ;

return user;

}

3. map(Function super T, ? extends U> mapper)和flatMap(Function super T, Optional> mapper)

源码:

/**

* If a value is present, apply the provided mapping function to it,

* and if the result is non-null, return an {@code Optional} describing the

* result. Otherwise return an empty {@code Optional}.

*

* @apiNote This method supports post-processing on optional values, without

* the need to explicitly check for a return status. For example, the

* following code traverses a stream of file names, selects one that has

* not yet been processed, and then opens that file, returning an

* {@code Optional}:

*

*

{@code

* Optional fis =

* names.stream().filter(name -> !isProcessedYet(name))

* .findFirst()

* .map(name -> new FileInputStream(name));

* }

*

* Here, {@code findFirst} returns an {@code Optional}, and then

* {@code map} returns an {@code Optional} for the desired

* file if one exists.

*

* @param The type of the result of the mapping function

* @param mapper a mapping function to apply to the value, if present

* @return an {@code Optional} describing the result of applying a mapping

* function to the value of this {@code Optional}, if a value is present,

* otherwise an empty {@code Optional}

* @throws NullPointerException if the mapping function is null

*/

public Optional map(Function super T, ? extends U> mapper) {

Objects.requireNonNull(mapper);

if (!isPresent())

return empty();

else {

return Optional.ofNullable(mapper.apply(value));

}

}

/**

* If a value is present, apply the provided {@code Optional}-bearing

* mapping function to it, return that result, otherwise return an empty

* {@code Optional}. This method is similar to {@link #map(Function)},

* but the provided mapper is one whose result is already an {@code Optional},

* and if invoked, {@code flatMap} does not wrap it with an additional

* {@code Optional}.

*

* @param The type parameter to the {@code Optional} returned by

* @param mapper a mapping function to apply to the value, if present

* the mapping function

* @return the result of applying an {@code Optional}-bearing mapping

* function to the value of this {@code Optional}, if a value is present,

* otherwise an empty {@code Optional}

* @throws NullPointerException if the mapping function is null or returns

* a null result

*/

public Optional flatMap(Function super T, Optional> mapper) {

Objects.requireNonNull(mapper);

if (!isPresent())

return empty();

else {

return Objects.requireNonNull(mapper.apply(value));

}

}

这两个函数,在函数体上没什么区别。唯一区别的就是入参,map函数所接受的入参类型为Function super T, ? extends U>,而flapMap的入参类型为Function super T, Optional>

在具体用法上,对于map而言:

如果User结构是下面这样的

public class User {

private String name;

public String getName() {

return name;

}

}

//取出name

String name = Optional.ofNullable(user).map(u -> u.getName()).get();

4. isPresent()和ifPresent(Consumer super T> consumer)

isPresent即判断value值是否为空,而ifPresent就是在value值不为空时,做一些操作。至于ifPresent(Consumer super T> consumer),用法也很简单

Optional.ofNullable(user).ifPressent(u -> {

})

实例: 节选网络上的几个实例

Optional optional1 = Optional.ofNullable(1);

Optional optional2 = Optional.ofNullable(null);

// isPresent判断值是否存在

System.out.println(optional1.isPresent() == true);

System.out.println(optional2.isPresent() == false);

以前写法:

1b7c0fa6e414358fdec0c758721356f7.png

Java8写法

a58068d97ea9098ae18c98079983ffa8.png

以前写法:

97443d3b74ab20e3115b8351cf5d3a1d.png

Java8写法:

a11ae046cbe3f55ac6f9680443fc5546.png

以前写法:

422f26d26a38c2665ff7b36c1f6e4184.png

Java8写法:

3c5ee15d405173d9b356eb59769fab86.png

Q.E.D.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值