Optional类主要解决空指针异常NullPointerException。
Optional 类(java.util.Optional)是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。

创建Optional 对象

声明一个空的Optional

通过静态工厂方法Optional.empty(),创建一个空的Optional 对象,Optional中只有私有的构造方法,所以只能在其类中查找已经提供的创建方法,比如如下提供的一个容器中没有任何值的返回类型

public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}

使用方法:

Optional<Car> optCar = Optional.empty(); 

依据一个非空值创建Optional

使用静态工厂方法Optional.of(T),依据一个非空值创建一个Optional对象:

public static <T> Optional<T> of(T value) {
return new Optional<>(value);
} Optional<String> optCar = Optional.of("sdfs");

由于这种方法创建时,会new Optional(T t),而在new的过程中,私有的构造函数对其传入的变量有检验:

 private Optional(T value) {
this.value = Objects.requireNonNull(value);
}

当传入的参数为null时会爆NullPointerException

3. 可接受null的Optional

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

如果car是null,那么得到的Optional对象就是个空对象。

读取Optional实例中的变量值

1. get()

如果此Optional中存在值,则返回该值,否则抛出NoSuchElementException。

public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}

比如:
Product构造函数(用于后面示例)

 public Product(Integer id, Integer num, BigDecimal price, String name, String category) {
this.id = id;
this.num = num;
this.price = price;
this.name = name;
this.category = category;
}
 Product prod = new Product(1, 1, new BigDecimal("15.5"), "面包", "零食");
Optional<Product> optProd = Optional.of(prod);
Optional<Product> optProdEmpty = Optional.empty();
Optional<Product> optProdNull = Optional.ofNullable(null);
Optional<Product> optProdDefault = Optional.ofNullable(prod);
System.out.println("optProd = " + optProd);
System.out.println("optProdEmpty = " + optProdEmpty);
System.out.println("optProdNull = " + optProdNull);
System.out.println("optProdDefault = " + optProdDefault);

输出结果:

optProd = Optional[com.bjmashibing.system.baierhu.stream.Product@23ab930d]
optProdEmpty = Optional.empty
optProdNull = Optional.empty
optProdDefault = Optional[com.bjmashibing.system.baierhu.stream.Product@23ab930d]

使用get获取值:只要是 Optional.empty,即Opention容器为null,就返回的是nullpointerException

2. orElse(T other)

public T orElse(T other) {
return value != null ? value : other;
}

调用该方法,如果Optional中为 null,则返回传入的值,否则会取出Optional中的具体值,这里可以做判空处理,即为null的时候如何处理问题

3. orElseGet(Supplier<? extends T> other)

orElseGet是orElse方法的延迟调用版,Supplier方法只有在Optional对象不含值时才执行调用。如果创建默认值是件耗时费力的工作,应该考虑采用这种方式(借此提升程序的性能),或者你需要非常确定某个方法仅在Optional为空时才进行调用,也可以考虑该方式(这种情况有严格的限制条件)

public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
 Optional<String> empty = Optional.ofNullable(null);
System.out.println(empty.orElse("There is no value present!"));
System.out.println(empty.orElseGet(()->{return "No value";}));

执行结果:

There is no value present!
No value

4. orElseThrow(Supplier<? extends X> exceptionSupplier)

orElseThrow和get方法非常类似,如果值存在,返回该值。如果Optional对象为空时都会抛出一个异常,但是使用orElseThrow你可以定制希 望抛出的异常类型。

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
//执行结果如下:
optProdEmpty.orElseThrow(() -> new ServiceException("ServiceException"));

//输出异常

java.lang.RuntimeException: ServiceException

at com.bjmashibing.system.baierhu.stream.OptionalTest.lambda$createOpentional$1(OptionalTest.java:20)
at java.util.Optional.orElseThrow(Optional.java:290)
at com.bjmashibing.system.baierhu.stream.OptionalTest.createOpentional(OptionalTest.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

5. ifPresent(Consumer<? super T> consumer)

在变量值存在时执行一个作为参数传入的方法,否则就不进行任何操作。

public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}

比如:

optProd.ifPresent(System.out::println);
optProd.ifPresent(item -> {
System.out.println(item.getName());
}
);

个人感觉就是打印一些信息而已,无实际作用

6.使用 isPresent()判断Optional 容器中是否包含对象

判断容器中是否包含值,用此方法可避免NoSuchElementException 异常。

public boolean isPresent() {
return value != null;
}

7.使用map从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));
}
}

比如:获取name值

//prodEmpty对象不知道是否为null
String name = null;
if(null != prodEmpty) {
name = prodEmpty.getName();
}else {
name = "test";
} //使用map
Optional<Product> optProd2 = Optional.ofNullable(prodEmpty);
name = optProdEmpty.map(Product::getName).orElse("test");

8.使用flatMap链接Optional对象

public class Product {
private Brand brand; public Brand getBrand() {
return brand;
} public void setBrand(Brand brand) {
this.brand = brand;
} public Optional<Brand> getBrandAsOptional(){
return Optional.ofNullable(brand);
}
} public class Brand {
private String name; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}
Product prod = new Product(1L, 1, new BigDecimal("15.5"), "面包", "零食");
Brand brand = new Brand();
brand.setName("达利园");
prod.setBrand(brand); String brandName = optProd.flatMap(Product::getBrandAsOptional).map(Brand::getName).orElse("other");
System.out.println(brandName);

这种写法可以不用多重判断,前面为null时每个过程中返回的都是一个null的Optional

注意:在域模型中使用Optional,是无法序列化的。所以可以写一个get方法返回Optional类型。

9.使用filter剔除特定的值

filter方法接受一个谓词作为参数。如果Optional对象的值存在,并且它符合谓词的条件, filter方法就返回其值;否则它就返回一个空的Optional对象。

public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
Product prod = new Product(1, 1, new BigDecimal("15.5"), "面包", "零食");
Optional<Product>optProd=Optional.ofNullable(prod);
Optional<Product>pr=optProd.filter(item -> item.getNum() > 1);
System.out.println("pr = " + pr);

输出:pr = Optional.empty

总结:Optional类的方法

本文大多转载于:https://blog.csdn.net/u014231523/article/details/102649003

java8中的Optional的更多相关文章

  1. Java8中的Optional操作

    作者:汤圆 个人博客:javalover.cc 前言 官人们好啊,我是汤圆,今天给大家带来的是<Java8中的Optional操作>,希望有所帮助,谢谢 文章纯属原创,个人总结难免有差错, ...

  2. Java8 中的 Optional

    从 Java 8 引入的一个很有趣的特性是 Optional  类.Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException) —— 每个 Java 程序员都 ...

  3. 使用Java8中的Optional类来消除代码中的null检查

    简介 Optional类是Java 8新增的一个类,Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException). —— 每个 Java 程序员都非常了解的异常 ...

  4. Java8 中的 Optional 相关用法

    基本方法: ofNullable() 为可能 null 的值创建一个 Optional 实例,  然后可以对该实例遍历/过滤, 判断是否存在,或者为空时执行.. ifPresent(...) 如果值存 ...

  5. Java8 新特性 Optional 类

    Optional 类的简介   Optional类的是来自谷歌Guava的启发,然后就加入到Java8新特性中去了.Optional类主要就是为子决解价值亿万的错误,空指针异常.   Optional ...

  6. 一篇文章教会你使用Java8中的Lambda表达式

    简介 Java 8为开发者带来了许多重量级的新特性,包括Lambda表达式,流式数据处理,新的Optional类,新的日期和时间API等.这些新特性给Java开发者带来了福音,特别是Lambda表达式 ...

  7. Java8中的Stream API

    本篇文章继续介绍Java 8的另一个新特性——Stream API.新增的Stream API与InputStream和OutputStream是完全不同的概念,Stream API是对Java中集合 ...

  8. java8中的stream().filter()的使用和Optional()

    转: https://www.cnblogs.com/yimiyan/p/5992440.html Optional: https://www.cnblogs.com/zhangboyu/p/7580 ...

  9. java8中的map和reduce

    java8中的map和reduce 标签: java8函数式mapreduce 2014-06-19 19:14 10330人阅读 评论(4) 收藏 举报  分类: java(47)  FP(2)  ...

随机推荐

  1. WPF 基础 - 绘画 1) 线段、矩形、圆弧及填充色

    1. 绘画 1.1 图形类型 Line X1.Y1.X2.Y2,Stroke,StrokeThickness Rectangle 矩形 Ellipse 椭圆 Polygon 多边形(自动闭合) Pol ...

  2. 攻防世界 reverse serial-150

    serial-150 suctf-2016 直接使用ida发现main函数中夹杂大片数据,应该是自修改代码,动态调试: 调试中发现,输入为16位,验证方法为:从头开始取一字符进行比较,比较通过检验后, ...

  3. 微信开发者工具导入 wepy 项目“app.json 未找到”报错解决方法

    版本信息: 微信开发者工具:1.03.2101150 wepy:2.0 wepy/cli:6.14.8 问题描述 按照 wepy 文档中的步骤新建项目: $ npm install @wepy/cli ...

  4. 给Nginx配置日志格式和调整日期格式

    效果对比 官方默认日志格式 # 官方默认日志格式 log_format main '$server_name $remote_addr - $remote_user [$time_local] &qu ...

  5. [图论]最优布线问题:prim

    最优布线问题 目录 最优布线问题 Description Input Output Sample Input Sample Output Hint 解析 代码 Description 学校有n台计算机 ...

  6. gitee 学习笔记

    这个流程只能是在自己的测试仓库中联系哟 首先创建一个自己的仓库 接下来安装git客户端,通过gitee官网给了一个例子创建ssh密钥 然后输入命令 get clone 你仓库的https 或者ssh地 ...

  7. Day09_44_Set集合_SortedSet01

    SortedSet集合 java.util.Set<interface> java.util.SortedSet<interface> 无序不可重复,但是存进去的数据可以按照元 ...

  8. C#入门到精通系列课程——第3章变量及运算符

    ◆本章内容 (1)变量是什么 (2)变量的声明及初始化 (3)常量 (4)运算符 (5)数据类型转换 (6)运算符优先级及结合性 (7)难点解答 ◆本章简述 很多人认为学习C#之前必须要学习C++,其 ...

  9. H5小技巧之——巧用<a>标签锚链接(#锚点链接 #页面特定位置 #DOM定位 #hash路由中使用锚链接)

    #作者:矩阵鱼--代码中游泳的咸鱼 前端开发中,常遇到定位到页面某特定位置的需求,JavaScript提供的el.scrollIntoView() 和 el.scrollIntoViewIfNeede ...

  10. ASP微信服务号H5客户登陆,且获取客户授权的用户基本信息

    ASP微信服务号H5客户登陆,且获取客户授权的用户基本信息是需要客户授权,下面讲解详细步骤: 第一步:客户点击登录页,自动跳转到微信服务器端获取code 第二步:用第一步获取的code去获取客户的ac ...