美文网首页
Java8 学习笔记

Java8 学习笔记

作者: lemontree93 | 来源:发表于2017-12-26 15:32 被阅读0次

    @(in action系列)[java8, lambda, stream]

    Java8 学习 java8 能高效的快捷的写出简介可读性强的高效率代码,这次的学习内容是:

    • java8 的接口默认方法defualt
    • java8 Optional类强大的判空功能

    默认方法

    默认方法是定义在接口中的实现了的方法,在实际开发中,一个接口完成了,并有很多的实现类实现了接口中的方法,如果实现方法已经是既定方法,如果再次在接口中添加接口时,所有的实现类都要实现接口中的方法,但是却不是所有的类都要实现该接口方法,所以引入了默认方法,在不改变实现类的情况下使用该默认方法。
    而且当接口被用户使用时,你是无法修改用户的实现类的。如何理解被用户使用?例如你实现了jdk中的接口,jdk的开发者后来在该接口中添加了新方法,你更新了jdk,那就要实现那个新方法,那是不是要爆炸?

    解决默认方法冲突的三条规则

    如果一个类使用相同的函数签名从多个地方(比如另一个类或接口)继承了方法,通过三条
    规则可以进行判断。

    • (1) 类中的方法优先级最高。类或父类中声明的方法的优先级高于任何声明为默认方法的优先级 。
    • (2) 如果无法依据第一条进行判断,那么子接口的优先级更高:函数签名相同时,优先选择拥有最具体实现的默认方法的接 口,即如果 B 继承了 A ,那么 B 就比 A 更加具体。
    • (3) 最后,如果还是无法判断,继承了多个接口的类必须通过显式覆盖和调用期望的方法,显式地选择使用哪一个默认方法的实现。

    重点介绍下第三种方法:
    下面有两个接口A,B,C实现了两个接口

    public interface A {
        default void hello() {
            System.out.println("Hello from A");
        }
    }
    public interface B {
        default void hello() {
            System.out.println("Hello from B");
        }
    }
    public class C implements B, A { }
    

    由于java编译器无法判断该实现哪个接口于是抛出异常 **Error: class C inherits unrelated defaults for hello()from types B and A **提示你去实现其中一个方法

    该冲突的解决方法就是:
    显式地选择调用接口B 中的方法

    public class C implements B, A {
        void hello(){
            B.super.hello();
        }
    }
    

    菱形继承问题

    再来看一种情况:

    public interface A{
        default void hello(){
            System.out.println("Hello from A");
        }
        public interface B extends A { }
        public interface C extends A { }
        public class D implements B, C {
            public static void main(String... args) {
            new D().hello();
        }
    }
    
    !Alt text]( image

    )
    这个时候显示的应该是A中的方法。

    总结一句话就是:哪个更具体,就用哪个的方法。

    用 Optional 取代 null

    在开发的过程中经常会遇到空指针异常,java8给出了解决的方案——Optional,但是值得注意的时候是否使用Optional和你的代码逻辑是有关系的,有时候就是要抛出空指针异常的。

    1. 声明一个空的 Optional
      正如前文已经提到,你可以通过静态工厂方法 Optional.empty ,创建一个空的 Optional
      对象:
      Optional<Car> optCar = Optional.empty();
    2. 依据一个非空值创建 Optional
      你还可以使用静态工厂方法 Optional.of ,依据一个非空值创建一个 Optional 对象:
      Optional<Car> optCar = Optional.of(car);
      如果 car 是一个 null ,这段代码会立即抛出一个 NullPointerException ,而不是等到你
      试图访问 car 的属性值时才返回一个错误。
    3. 可接受 null 的 Optional
      最后,使用静态工厂方法 Optional.ofNullable ,你可以创建一个允许 null 值的 Optional
      对象:
      Optional<Car> optCar = Optional.ofNullable(car);
      如果 car 是 null ,那么得到的 Optional 对象就是个空对象

    使用 map 从 Optional 对象中提取和转换值

    用map提取和转换值类似于Stream中的map
    例如:

    Optional<Insurance> optInsurance = Optional.ofNullable(insurance);
    Optional<String> name = optInsurance.map(Insurance::getName);
    

    [图片上传失败...(image-68ed55-1514271060077)]

    使用 flatMap 链接 Optional 对象

    使用map是无法使用链式的表达方式的,因为map返回的是一个Optional对象,而flatMap则可以从中抽取出泛型对象进行链式表达。
    例如:

    public String getCarInsuranceName(Optional<Person> person) {
        return person.flatMap(Person::getCar)
        .flatMap(Car::getInsurance)
        .map(Insurance::getName)
        .orElse("Unknown");
    }
    

    [图片上传失败...(image-5230b9-1514271060077)]
    看看流程


    流程

    总结map操作的是Optional< SUbject >,而flatMap操作的是Optional< Optional< SUbject > >

    Optional对象中的方法

    Optional中很多方法可以用作代码优化的点!操作类似于

    这里写图片描述

    用Optional的几点建议

    1. 用 Optional 封装可能为 null 的值
      Optional<Object> value = Optional.ofNullable(map.get("key"));
    2. 在封装工具类的时候,返回的类型尽量不要用基础类型的Optional对象
      比如能返回Optional< Integer >的尽量不要用OptionalInt,因为基础类型的Optional没有map、filter等的方法。
    3. 尽量吧所有内容整合起来,意思就是像流那样采用链式操作。

    相关文章

      网友评论

          本文标题:Java8 学习笔记

          本文链接:https://www.haomeiwen.com/subject/acfjgxtx.html