JDK8特性深刻学习笔记-Optional和方法引用(3)

Optional

Optional是一个独立的类型,在实际应用中,主要是为了解决NullPointerExceptionjava

基于值的类

Optional类为 终态类(class 前有 final修饰)
Optional是 基于值的类(Value-based Classes)(还有LocalDateTime),对于基于值的类有如下特色
  • 是final不可变的(可是有可能存在可变对象的引用)
  • 有hashcode和toString的实现,可是这些实现仅仅是根据实例自己的状态,不会依赖于其余的变量
  • 不会使用身份敏感的操做例如“==” ,或者hashcode或者锁等。
  • 仅仅依靠equals方法来判断相等性
  • 不会拥有可访问的构造方法,经过工厂方法来建立的,工厂方法并不保证明例的一致性
  • 当相等时是能够任意替换的。

Optional的构造方法

  • empty():构造一个容器内容为空的Optional
  • of():直接new一个内容为T的Optional,调用者需确保T不能为空,不然抛出空指针异常。
  • ofNullable():构造一个可能为null也可能不为null的对象,若是T为null,则调用empty,不然调用of

Optional的基本使用

Optional<String> optional = Optional.of("hello");
// 面向对象风格的写法(不推荐)
if(optional.isPresent()){
    System.out.println(optional.get())
}

// 经过函数式风格
optional.ifPresent(i -> System.out.println(optional.get()));

若是不在optional.get()方法外不使用isPresent,idea会提示警告,若是Optional的内容为空,get方法会抛出异常。ide

orElse(T)

optional.orElse("T");

若是内容为空,则将内容指定为T,不然不作任何的改变。函数

避免集合的空判断

Person person = new Person();
List<String> strings = new ArrayList<>();
person.setList(strings);
Optional.ofNullable(person).map(item -> item.getList()).orElse(Collections.emptyList());

Optional做为方法参数

public void test(Optional optional){

}

此时idea会提示警告,Optional是没有序列化的,不要做为变量传入,应该使用函数式的方式来传入。this

方法引用(method reference)

在何时能够使用方法引用: 仅仅当lambda表达式里的实现能刚好被一个方法引用所表示,可是不少状况下lambda内容是较为复杂的。因此方法引用算是Lambda表达式的一个语法糖。idea

方法引用的简单使用

List<String> list = Arrays.asList("1", "2", "3");

list.forEach(System.out::println)

咱们能够将方法引用看做是一个函数指针(function pointer)(C中的概念,将指针指向一个函数)。
方法引用的要求:你所实现的lambda方法体,刚好有一个方法完成一样的事情:一样的参数和返回值,一样的功能逻辑。指针

方法引用共分为4类:code

  • 类名::静态方法
  • 引用名::实例方法名
  • 类目::实例方法名
  • 构造方法引用,类名::new

其中类目::实例方法名这个并不容易理解,例如对象

public class Person {
    private Integer age;
    private String name;

    public int compareName(Person person){
        return this.name.compareToIgnoreCase(person.getName());
    }
}

public class Test {
    public static void main(String[] args) {
        Person person1 = new Person();
        person1.setName("abc");
        Person person2 = new Person();
        person2.setName("zdf");
        List<Person> list = Arrays.asList(person1, person2);
        list.sort(Person::compareName);
        list.forEach(i -> System.out.println(i.getName()));
    }
}

sort方法接受的是两个参数的Consumer,而comaperName方法只有一个入参,可是方法引用成功。缘由是这个CompareName是在Person类中实现的方法,其中的一个比较对象是这个方法的一个属性,因此默认Consumer的第一个参数即为这个类自己接口

默认方法

interface MyInterface1{
    default void myMethod(){
        System.out.println("1");
    }
}
interface MyInterface2{
    default void myMethod(){
        System.out.println("2");
    }
}

public class MyClass implements MyInterface1, MyInterface2{

    @Override
    public void myMethod(){
        MyInterface2.super.myMethod();
    }
}

接口中已经支持了默认方法实现。可是若是同时实现两个同名默认方法实现,编译器由于不知道到底使用哪个,而会报错。这时候,必须使用重写myMethod方法,显式的告诉编译器须要选择哪一个具体方法实现。get

public class MyImpl1 implements MyInterface1 {
    @Override
    public void myMethod() {
        System.out.println("aa");
    }
}

public class MyClass extends MyImpl1 implements MyInterface2{
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        myClass.myMethod();
    }
}

java认为实现类的优先级大于default默认方法的优先级,因此上面代码将打印aa。

相关文章
相关标签/搜索