到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。
Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
(1)static
@Test
public void test01(){
Optional opt = Optional.empty();
System.out.println(opt);
}
(2)static
@Test
public void test02(){
String str = "hello";
Optional opt = Optional.of(str);
System.out.println(opt);
}
(3)static
@Test
public void test03(){
String str = null;
Optional opt = Optional.ofNullable(str);
System.out.println(opt);
}
@Test
public void test04(){
String str = "hello";
Optional opt = Optional.of(str);
System.out.println(opt.get());
}
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);
}
如果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);
}
如果Optional容器中非空,就返回所包装值,如果为空,就抛出你指定的异常类型代替原来的NoSuchElementException
@Test
public void test07(){
String str = null;
Optional opt = Optional.ofNullable(str);
String string = opt.orElseThrow(()->new RuntimeException("值不存在"));
System.out.println(string);
}
@Test
public void test08(){
Optional op = Optional.of("hello");
boolean present = op.isPresent();
System.out.println(present);
}
判断Optional容器中的值是否存在,如果存在,就对它进行Consumer指定的操作,如果不存在就不做
@Test
public void test09(){
Optional op = Optional.of("hello");
op.ifPresent(s -> System.out.println("存在值"));
}
判断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);
}
案例:
(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));
}
案例:
(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());
}