JDK8新特性之Optional类

简介: JDK8新特性之Optional类

Optional类


到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。


Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。


1 API


1.1 创建Optional对象


(1)static Optional empty() :用来创建一个空的Optional

@Test
public void test01(){
    Optional<String> opt = Optional.empty();
    System.out.println(opt);
}


(2)static Optional of(T value) :用来创建一个非空的Optional

@Test
public void test02(){
    String str = "hello";
    Optional<String> opt = Optional.of(str);
    System.out.println(opt);
}


(3)static Optional ofNullable(T value) :用来创建一个可能是空,也可能非空的Optional

//一般用这一种创建

@Test
public void test03(){
    String str = null;
    Optional<String> opt = Optional.ofNullable(str);
    System.out.println(opt);
}


1.2 从Optional容器中取出所包装的对象

(1)T get() :要求Optional容器必须非空

@Test
public void test04(){
    String str = "hello";
    Optional<String> opt = Optional.of(str);
    System.out.println(opt.get());
}


(2)T orElse(T other) :

用的最多

orElse(T other) 与ofNullable(T value)配合使用,

如果Optional容器中非空,就返回所包装值,如果为空,就用orElse(T other), other是指定的默认值(备胎)代替

@Test
public void test05(){
    String str = "涤魂圣枪";
    Optional<String> opt = Optional.ofNullable(str);
    String string = opt.orElse("圣枪游侠");
    System.out.println(string);
}


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

如果Optional容器中非空,就返回所包装值,如果为空,就用Supplier接口的Lambda表达式提供的值代替

@Test
public void test06(){
   Optional<String> optional = Optional.ofNullable("涤魂圣枪");
        String s = optional.orElseGet(() -> "圣枪游侠");
    //        String s = optional.orElseGet(() -> new String("圣枪游侠"));供给型接口
        System.out.println(s);
}


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

如果Optional容器中非空,就返回所包装值,如果为空,就抛出你指定的异常类型代替原来的NoSuchElementException

@Test
public void test07(){
    String str = null;
    Optional<String> opt = Optional.ofNullable(str);
    String string = opt.orElseThrow(()->new RuntimeException("optional值为空"));
    System.out.println(string);
}


3、其他方法

(1)boolean isPresent() :判断Optional容器中是否有值

@Test
public void test08(){
    Optional<String> op = Optional.of("hello");
    boolean present = op.isPresent();
    System.out.println(present);
}


(2)void ifPresent(Consumer<? super T> consumer) :

判断Optional容器中的值是否存在,如果存在,就对它进行Consumer指定的操作,如果不存在就不做

@Test
public void test09(){
    Optional<String> op = Optional.of("hello");
    op.ifPresent(s -> System.out.println("存在值"));
}


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

判断Optional容器中的值是否存在,如果存在,就对它进行Function接口指定的操作,如果不存在就不做

@Test
public void test10(){
    String str = "Hello";
    Optional<String> opt = Optional.ofNullable(str);
    //判断是否是纯字母单词,如果是,转为大写,否则保持不变
    String result = opt.filter(s->s.matches("[a-zA-Z]+")).
        map(s -> s.toLowerCase()).
        orElse(str);
    System.out.println(result);
}



2 练习


2.1 练习1


案例:


(1)声明一个Girl类型,包含姓名(String)属性

(2)声明一个Boy类型,包含姓名(String),女朋友(Girl)属性

(3)在测试类中,创建一个Boy对象,并

如果他有女朋友,显示他女朋友名称;

如果他没有女朋友,他的女朋友默认为“嫦娥”,即只能欣赏“嫦娥”了


class Girl{
  private String name;
  public Girl(String name) {
    super();
    this.name = name;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  @Override
  public String toString() {
    return "Girl [name=" + name + "]";
  }
}
class Boy{
  private String name;
  private Girl girlFriend;
  public Boy(String name, Girl girlFriend) {
    super();
    this.name = name;
    this.girlFriend = girlFriend;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public Girl getGirlFriend() {
    return girlFriend;
  }
  public void setGirlFriend(Girl girlFriend) {
    this.girlFriend = girlFriend;
  }
  @Override
  public String toString() {
    return "Boy [name=" + name + ", girlFriend=" + girlFriend + "]";
  }
}


测试类

  public static void main(String[] args) {
//    Boy boy = new Boy("张三",null);
    Boy boy = new Boy("张三",new Girl("翠翠"));
    Optional<Girl> grilFriend = Optional.ofNullable(boy.getGirlFriend());
    Optional.of(grilFriend.orElse(new Girl("嫦娥"))).ifPresent(g->System.out.println(g));
  }



2.2 练习2

案例:


(1)声明学生类,包含姓名和年龄

(2)添加几个学生对象到一个ArrayList集合中

(3)对集合中的学生进行操作,找出年龄大于30岁的,并取出第一个学生,如果没有这样的学生,用无参构造new一个学生对象,打印学生信息


学生类示例代码:

class Student{
  private String name;
  private int age;
  public Student(String name, int age) {
    super();
    this.name = name;
    this.age = age;
  }
  public Student() {
    super();
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public int getAge() {
    return age;
  }
  public void setAge(int age) {
    this.age = age;
  }
  @Override
  public String toString() {
    return "Student [name=" + name + ", age=" + age + "]";
  }
}


测试类

@Test
public void test1(){
    ArrayList<Student> list = new ArrayList<>();
    list.add(new Student("张三", 23));
    //...
    //取出流中第一个年龄大于30岁的学生的年龄,并打印它的年龄,如果没有,用无参构造创建一个学生对象
    Student stu = list.stream()
        .filter(s -> s.getAge()>30)
        .findFirst().orElse(new Student());
    System.out.println("学生的年龄:" + stu.getAge());
}
相关文章
|
12天前
|
Java API 开发者
【Java字节码操控新篇章】JDK 22类文件API预览:解锁Java底层的无限可能!
【9月更文挑战第6天】JDK 22的类文件API为Java开发者们打开了一扇通往Java底层世界的大门。通过这个API,我们可以更加深入地理解Java程序的工作原理,实现更加灵活和强大的功能。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来!
|
10天前
|
Java API 开发者
【Java字节码的掌控者】JDK 22类文件API:解锁Java深层次的奥秘,赋能开发者无限可能!
【9月更文挑战第8天】JDK 22类文件API的引入,为Java开发者们打开了一扇通往Java字节码操控新世界的大门。通过这个API,我们可以更加深入地理解Java程序的底层行为,实现更加高效、可靠和创新的Java应用。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来,并积极探索类文件API带来的无限可能!
|
28天前
|
存储 Java
【Java集合类面试七】、 JDK7和JDK8中的HashMap有什么区别?
JDK7中的HashMap使用数组加链表解决冲突,而JDK8增加了红黑树结构以优化链表过长时的性能,提高查找效率。
|
1月前
|
Java API
JDK8到JDK25版本升级的新特性问题之使用Collectors.teeing()来计算一个列表中学生的平均分和总分如何操作
JDK8到JDK25版本升级的新特性问题之使用Collectors.teeing()来计算一个列表中学生的平均分和总分如何操作
|
1月前
|
Java API Apache
JDK8到JDK24版本升级的新特性问题之在Java中,HttpURLConnection有什么局限性,如何解决
JDK8到JDK24版本升级的新特性问题之在Java中,HttpURLConnection有什么局限性,如何解决
|
1月前
|
Oracle Java 关系型数据库
JDK8到JDK29版本升级的新特性问题之未来JDK的升级是否会成为必然趋势,如何理解
JDK8到JDK29版本升级的新特性问题之未来JDK的升级是否会成为必然趋势,如何理解
|
1月前
|
Oracle 安全 Java
JDK8到JDK28版本升级的新特性问题之在Java 15及以后的版本中,密封类和密封接口是怎么工作的
JDK8到JDK28版本升级的新特性问题之在Java 15及以后的版本中,密封类和密封接口是怎么工作的
|
15天前
|
Java 编译器 API
JDK8新特性--lambda表达式
JDK8的Lambda表达式是Java语言的一大进步。它为Java程序提供了更多的编程方式,让代码更加简洁,也让函数式编程的概念在Java中得到了体现。Lambda表达式与Java 8的其他新特性,如Stream API、新的日期时间API一起,极大地提高了Java编程的效率和乐趣。随着时间的流逝,Java开发者对这些特性的理解和应用将会越来越深入,进一步推动Java语言和应用程序的发展。
8 0
|
1月前
|
算法 Java iOS开发
JDK8到JDK27版本升级的新特性问题之JDK 17中G1在资源占用方面有何变化
JDK8到JDK27版本升级的新特性问题之JDK 17中G1在资源占用方面有何变化
|
1月前
|
XML JSON Java
JDK8到JDK26版本升级的新特性问题之在JDK 13中,字符串文本块改进字符串嵌入是如何实现的
JDK8到JDK26版本升级的新特性问题之在JDK 13中,字符串文本块改进字符串嵌入是如何实现的