JAVA8新特性之Optional类以及接口默认方法

为了尽量避免空指针在编码中给我们带来的问题,JAVA8提供了一个包装类Optional来解决空指针异常的问题,该类中包含了许多的方法,一起看看
Optional.of(T t)
该方法用于创建一个Optional实例,T为我们想要创建的类型,比如我们想创建一个Student类型的对象,可以这样写:

Optional<Student> optional=Optional.of(new Student());

在Optional的泛型中放入我们想要新建的对象,用于接收,这样我们就新建了由Optional包装起来的Student类,当我们想取出该student对象时,调用.get()方法:

@Test
    public void test1(){
        Optional<Student> optional=Optional.of(new Student());
        Student student=optional.get();
        System.out.println(student);
    }

这里我们创建的是一个没有任何属性的student对象,运行结果如下:
在这里插入图片描述
Optional.empty()
该方法用于创建一个空的Optional实例

@Test
    public void test2(){
        Optional<String > optional = Optional.empty();
        System.out.println(optional.get());
    }

而运行后,不再会报空指针异常,而是如下信息:
在这里插入图片描述
信息告诉我们get方法没有获取到值,也就是optional包装的String没有值,这样我们就可以很快的定位到报空的位置,而不用像以前一样一级一级进行断点调试

Optional.ofNullable(T t):若t不为null,创建Optional实例,否则创建空实例,我们可以将它理解为.of()与.empty()方法的综合

isPresent():判断是否包含值
该方法的逻辑应该在平时编码中会经常用到,比如我们要判断一个对象是否有值,有值才会对其进行操作

	Optional<Student> optional = Optional.ofNullable(new Student());
    if (optional.isPresent()){
            System.out.println(optional.get());
        }

orElse(T t):如果调用对象包含值,返回该值,否则返回t
在上一步的基础上,我们继续这个方法,如果该optional对象有值时,我们就返回,否则返回我们指定的一个值:

	Optional<Student> optional = Optional.ofNullable(new Student());
    Student student=optional.orElse(new Student(001,"张三",18,183.2));
    System.out.println(student);

运行结果:
在这里插入图片描述
由于我们声明了一个无参的student,该对象有默认值,直接输出打印
接下来我们传入一个空对象

	Optional<Student> optional = Optional.ofNullable(null);
    Student student=optional.orElse(new Student(001,"张三",18,183.2));
    System.out.println(student);

运行结果:
在这里插入图片描述
通过使用替代值的方式,我们就能很好的避免空指针的发生

orElseGet(Supplier s):如果调用对象包含值,返回该值,否则返回S获得的值
该方法与orElse方法类似,但它传入的是一个函数式接口,也就是意味着,在orElse方法的基础上,我们还可以通过lambda表达式对替代的值做一些处理。
比方有一个student集合,数据如下:

   List<Student> stus= Arrays.asList(
            new Student("张三",16,168.25, Student.Status.FREE),
            new Student("李四",48,178.25,Student.Status.VOCATION),
            new Student("王五",36,148.45,Student.Status.BUSY),
            new Student("赵六",56,180.68,Student.Status.FREE),
            new Student("田七",18,180.68,Student.Status.VOCATION)

    );

现在我们要对集合中的数据进行一次判断,如果没有身高大于181的学生,则返回我们指定的数据,否则返回空对象,利用orElse方法我们可以这样写:


        Optional<Student> optional = Optional.ofNullable(null);
        Student student=optional.orElseGet(() ->{
           boolean b = stus.stream().anyMatch((e) ->e.getHeight()>181);
            System.out.println(b);
           if (b){
               return new Student();
           }else {
               return new Student(001,"张三",18,183.2);
           }
        });

        System.out.println(student);

map(Function f)、 flatMap(Function mapper):如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
这个方法之前在streamAPI中我们提到过,这里就不多说

接下来我们说一个比较常见的空指针情况,我们有一个班级类MyClass,以及一个学生类MyStudent,班级中有学生,但不一定有某个名叫A的学生,但名叫A的学生是一定存在的。我们要做的是得到该班级中包含的学生姓名,两个实体类如下:
在这里插入图片描述
在这里插入图片描述
在传统方法中,为了避免空指针,我们会这样写:

public String getStudentName(MyClass myClass){
        if (myClass!=null){
            MyStudent student=myClass.getMyStudent();
            if (student!=null){
                return student.getName();
            }
        }
        return "学生";
    }

然后写下一个测试方法调用该方法得到我们想要的值:

@Test
    public void test5(){
     MyClass myclass=new MyClass();
     String name=getStudentName(myclass);
     System.out.println(name);
    }

先对MyClass对象进行非空判断,再对student对象进行非空判断,利用Optional类,我们可以这样写:
在这里插入图片描述
放入一个类型为MyStudent类型的空optional类,而获取名字的方法则可以写成这样:

public String getStudentName2(Optional<MyClass> myClass){
       return myClass.orElse(new MyClass()).getOptional().orElse(new MyStudent("学生")).getName();
    }

为了防止MyClass为空,我们将传入的MyClass使用Optional包装起来,在返回时使用orElse方法进行避免,而后再调用其中的get方法得到其中的Optional属性,再对该属性进行一次orElse避免空指针

接下来再说一说接口默认方法:在JAVA8中,允许接口中含有实现的方法(默认方法),使用default关键字修饰即可:

public interface MyFun {
    default String getName(){
        return "aaa";
    }
}

在这种情况下,我们也许会碰到一个冲突的问题,比如我们现在有一个类,也含有同样的方法:

public class TestClass {
    public String getName(){
        return "bbb";
    }
}

有一个类既实现了MyFun接口,又继承了TestClass类:
在这里插入图片描述
那么当我们调用其中的getName方法时,会调用哪个方法呢?
在这里插入图片描述
查看运行结果:
在这里插入图片描述
最终打印的是bbb,也就是调用了父类中的方法,这就说明:当接口中定义了默认方法,而另外一个父类中又定义了一个同名的方法时,会选择父类中的方法。
另外,还会有一个接口冲突的情况出现,假设我们有两个含有同样默认方法的接口,这是第二个:
在这里插入图片描述
而有一个实现类实现了这两个接口
在这里插入图片描述
而这时因为我们没有重写方法导致类名报错,此时因为两个接口的方法相同,若如果我们想实现其中一个,比如我们想实现MyFun中的方法,就需要这么写:

 @Override
    public String getName() {
        return MyFun.super.getName();
    }

运行结果:
在这里插入图片描述
同样地,若我们想实现MyDefault中的方法,则把类名更换即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值