Java(十五)----Optional类

1. 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 opt = Optional.empty();
    System.out.println(opt);
}

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

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

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

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

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

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

@Test
public void test04(){
    String str = "hello";
    Optional 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 = "hello";
    Optional opt = Optional.ofNullable(str);
    String string = opt.orElse("atguigu");
    System.out.println(string);
}

(3)T orElseGet(Supplier other) :

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

@Test
public void test06(){
    String str = null;
    Optional opt = Optional.ofNullable(str);
    String string = opt.orElseGet(String::new);
    System.out.println(string);
}

(4) T orElseThrow(Supplier exceptionSupplier)

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

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

3、其他方法

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

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

(2)void ifPresent(Consumer consumer) :

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

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

(3) Optional map(Function mapper)

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

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

4 练习

4.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 grilFriend = Optional.ofNullable(boy.getGirlFriend());
		Optional.of(grilFriend.orElse(new Girl("嫦娥"))).ifPresent(g->System.out.println(g));
	}

4.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 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());
}

你可能感兴趣的:(Java,java)