java8新特性-Optional

转载整理自:作者:孤独烟 出处: http://rjzheng.cnblogs.com/

调用示例

optional是java8的一个新特性,通过这个类我们可以优雅的解决 NullPointException 的问题,避免了大量的为空判断
先给几个例子
1、
旧写法:

public String getCity(User user)  throws Exception{
        if(user!=null){
            if(user.getAddress()!=null){
                Address address = user.getAddress();
                if(address.getCity()!=null){
                    return address.getCity();
                }
            }
        }
        throw new Excpetion("取值错误"); 
    }

java8:

public String getCity(User user) throws Exception{
    return Optional.ofNullable(user)
                   .map(u-> u.getAddress())
                   .map(a->a.getCity())
                   .orElseThrow(()->new Exception("取指错误"));
}

2、
旧写法:

if(user!=null){
    dosomething(user);
}

java8:

Optional.ofNullable(user)
    .ifPresent(u->{
        dosomething(u);
});

3、
旧写法:

public User getUser(User user) throws Exception{
    if(user!=null){
        String name = user.getName();
        if("zhangsan".equals(name)){
            return user;
        }
    }else{
        user = new User();
        user.setName("zhangsan");
        return user;
    }
}

java8:

public User getUser(User user) {
    return Optional.ofNullable(user)
                   .filter(u->"zhangsan".equals(u.getName()))
                   .orElseGet(()-> {
                        User user1 = new User();
                        user1.setName("zhangsan");
                        return user1;
                   });
}

4、optional不为空返回object,为空返回null

Tally tally = tallyRepository.findById((long) 99).orElse(null);//orElseGet提示异常
if(tally != null){
	System.out.println(tally.getRemarks());
}

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

(1)Optional(T value)

构造函数,它是private权限的,不能由外部调用
在这里插入图片描述

(2)empty()

返回一个空的 Optional 实例
源码:(Optional类内部还维护一个value为null的对象)

private static final Optional<?> EMPTY = new Optional<>();
private Optional() {
    this.value = null;
}
public static<T> Optional<T> empty() {
    @SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}

(3)of(T value)

返回一个指定非null值的Optional,当Value值为空时,会报NullPointerException异常
源码:

public static <T> Optional<T> of(T value) {
    return new Optional<>(value);
}

(4)ofNullable(T value)

如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional
源码:

public static <T> Optional<T> ofNullable(T value) {
    return value == null ? empty() : of(value);
}

(5)of(T value)与ofNullable(T value)区别

当传入的value值为null时,of(T value)会报空指针(NullPointerException)异常;ofNullable(T value)不会抛出空指针异常而会直接返回一个EMPTY对象。当我们在运行过程中,不想隐藏空指针异常而是要立刻抛出则使用Of函数

2、orElse(T other),orElseGet(Supplier<? extends T> other)和orElseThrow(Supplier<? extends X> exceptionSupplier)

(1)T orElse(T other):如果存在该值,返回值, 否则返回 other
(2)T orElseGet(Supplier<? extends T> other):如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果
(3) T orElseThrow(Supplier<? extends X> exceptionSupplier):如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常
测试代码:

@Test
public void test() {
    User user1 = null;
    try {
	Optional.ofNullable(user1).orElseThrow(()->new Exception("用户不存在"));
	} catch (Exception e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
	}
    User user2 = null;
    user2 = Optional.ofNullable(user2).orElse(createUser());
    System.out.println(user2.getEmail());
    User user3 = null;
    user3 = Optional.ofNullable(user3).orElseGet(() -> createUser());
    System.out.println(user3.getEmail());
    
}
public User createUser(){
    User user = new User();
    user.setEmail("764682881@qq.com");;
    return user;
}

orElse(T other)和orElseGet的区别:当user值不为null时,orElse函数依然会执行createUser()方法,而orElseGet函数并不会执行createUser()方法,由于orElseGet()不是每次都会调用传入的方法,所以orElseGet()方法在性能上要优于orElse()方法,orElseThrow则是当值为null时,直接抛一个异常

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

(1)map(Function<? super T, ? extends U> mapper):如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optiona
源码:

 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));
    }
}

(2)flatMap(Function<? super T, Optional> mapper):如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的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));
    }
}

Map与flatMap唯一区别的就是入参,map函数所接受的入参类型为Function<? super T, ? extends U>,而flapMap的入参类型为Function<? super T, Optional>,即Map入参方法返回的参数是对象,flatMap入参方法返回的是Optional
调用:
<1>user结构为:

public class User {
    private String name;
    public String getName() {
        return name;
    }
}

使用map

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

<2>user结构为:

public class User {
    private String name;
    public Optional<String> getName() {
        return Optional.ofNullable(name);
    }
}

使用flatMap

String city = Optional.ofNullable(user).flatMap(u-> u.getName()).get();

**

4、isPresent()和ifPresent(Consumer<? super T> consumer)

**
isPresent即判断value值是否为空,而ifPresent就是在value值不为空时,做一些操作。这两个函数的源码如下
注意:最好不要把

if (user != null){
   // TODO: do something
}

写成:

User user = Optional.ofNullable(user);
if (Optional.isPresent()){
   // TODO: do something
}

这种写法Optional就丧失了意义

public final class Optional<T> {
    //省略....
    public boolean isPresent() {
        return value != null;
    }
    //省略...
    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }
}

ifPresent(Consumer<? super T> consumer),用法如下所示

Optional.ofNullable(user).ifPresent(u->{
    // TODO: do something
});

5、filter(Predicate<? super T> predicate)

filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty
源码:

public final class Optional<T> {
    //省略....
   Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
}

用法示例:

Optional<User> user1 = Optional.ofNullable(user).filter(u -> u.getName().length()<6);

如上所示,如果user的name的长度是小于6的,则返回。如果是大于6的,则返回一个EMPTY对象。

6、get()

T get():如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException

### 回答1: Java8中的Optional类是一个容器对象,可以包含null或非null值。它提供了一种优雅的方式来处理null值,避免了NullPointerException异常的出现。Optional类可以用于返回值、方法参数和实例变量等场景中,使代码更加简洁、清晰和安全。使用Optional类可以使代码更加健壮,减少了代码中的null检查和异常处理,提高了代码的可读性和可维护性。 ### 回答2: Optional类是Java 8中新引入的一个类,它的主要作用是在避免NullPointerException的情况下将null值返回给调用者。这个类是一个容器对象,它可以保存非空的对象,也可以保存空值(null)。 Optional类提供了通过判断一个对象是否为空来避免空指针异常的方式。它可以在代码中替换传统的null判断,这样可以更加方便地编写代码,并且可以使代码更加健壮。 在Java中,如果一个方法返回值为null,那么在调用该方法返回值的时候,会有可能抛出NullPointerException异常。而Optional类的出现可以帮助我们避免这种情况的出现,在调用Optional类的get()方法时,如果Optional类中保存的对象不为null,就会返回该对象,否则抛出一个NoSuchElementException异常。 Optional类还提供了一些方法来简化代码,比如orElse()方法,如果Optional类中保存的对象不为null,则返回该对象,否则返回指定的default值。还有ifPresent()方法,当Optional类中保存的对象不为null时,会执行指定的代码,否则不执行。 总之,Optional类是Java 8中一个很有用的类,它可以帮助我们更加方便地处理null值,避免空指针异常的出现,并且可以简化代码。但是需要注意的是,不应该滥用Optional类,因为它并不是完美的解决方案,有时候需要对null值进行特殊处理。 ### 回答3: Java 8在语言层面上增加了一个新的类:Optional。这是一个特殊的容器对象,可以包含一个null或非null的值。 Optional的目的是解决Java中的null引用问题。在Java中,如果一个变量被赋值为null,而我们试图调用该变量所对应的方法,那么就会出现NullPointerException异常。 使用Optional可以避免这种情况的发生。如果一个变量是Optional对象,那么我们必须显式地检查该对象是否包含非null的值,才能对其进行操作。这样,在我们试图调用该变量所对应的方法之前,就可以避免空指针异常的发生。 Optional类提供了很多方法来判断是否有值、获取值、如果没有值则返回默认值等等,使得我们可以更加方便地处理空值。 下面是一些Optional类提供的方法: 1. Optional.of(T value):创建一个包含非null值的Optional对象,如果T为null,则抛出NullPointerException异常。 2. Optional.ofNullable(T value):创建一个Optional对象,如果T为null,则该对象为空。 3. Optional.empty():创建一个空的Optional对象。 4. get():如果值存在,则返回该值,否则抛出异常。 5. orElse(T other):如果值存在,则返回该值,否则返回其他默认值。 6. isPresent():返回一个boolean类型的值,表示该Optional对象是否包含值。 7. ifPresent(Consumer<? super T> consumer):如果该Optional对象包含值,则对该值执行给定的操作。 在编写Java程序时,我们应该始终努力避免使用null值。使用Optional类,可以使得我们的代码更加健壮、可读性更强。但是,过多地使用Optional可能会导致代码过于冗长,所以在使用的过程中需要权衡利弊。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值