Java8新特性 转载https://www.jianshu.com/p/0bf8fe0f153b

一、接口的默认方法

允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做默认方法

interface Formula {
    double calculate(int a);

    default double sqrt(int a) {
        return Math.sqrt(a);
    }
}

Formula接口在拥有calculate方法之外同时还定义了sqrt方法,实现了Formula接口的子类只需要实现一个calculate方法,默认方法sqrt将在子类上可以直接使用。

Formula formula = new Formula() {
    @Override
    public double calculate(int a) {
        return sqrt(a * 100);
    }
};

formula.calculate(100);     // 100.0
formula.sqrt(16);           // 4.0

需要注意:如重写default方法权限需大于default为public。

二、Lambda 表达式

老版本的Java中是如何排列字符串的:

List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");

Collections.sort(names, new Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        return b.compareTo(a);
    }
});

只需要给静态方法 Collections.sort 传入一个List对象以及一个比较器来按指定顺序排列。通常做法都是创建一个匿名的比较器对象然后将其传递给sort方法。

在Java 8 中你就没必要使用这种传统的匿名对象的方式了,Java 8提供了更简洁的语法,lambda表达式:

Collections.sort(names, (String a, String b) -> {
    return b.compareTo(a);
});

看到了吧,代码变得更段且更具有可读性,但是实际上还可以写得更短:

Collections.sort(names, (String a, String b) -> {
    return b.compareTo(a);
});

    a.参数的数据类型可以省略
    b.如果参数只有一个,那么小括号也可以省略
    c.如果{}中方法体和返回值语句可以写成一句代码,那么{},return关键字,以及后面的分号可以同时省略 

案例1:
    //标准格式
    new Thread(()->{System.out.println("执行了...");}).start();
    //省略格式
    new Thread(()->System.out.println("执行了...")).start();

案例2:
    //标准格式 
    Arrays.sort(arr,(Integer o1, Integer o2)->{return o2 - o1;});
    //省略格式
    Arrays.sort(arr,(o1,o2)->o2 - o1);

案例3:
    //标准格式
    Arrays.sort(students,(Student o1, Student o2)->{return o2.getName().length() - o1.getName().length();});
    //省略格式
    Arrays.sort(students,(o1, o2)->o2.getName().length() - o1.getName().length());
Collections.sort(names, (String a, String b) -> {
    return b.compareTo(a);
});
Collections.sort(names, (a, b) -> b.compareTo(a));

前提为编译器可以自动推导出参数类型

三、函数式接口

每一个lambda表达式都对应一个类型,通常是接口类型。而“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。因为 默认方法 不算抽象方法,所以你也可以给你的函数式接口添加默认方法。
将lambda表达式当作任意只包含一个抽象方法的接口类型,确保你的接口一定达到这个要求,你只需要给你的接口添加 @FunctionalInterface 注解,编译器如果发现你标注了这个注解的接口有多于一个抽象方法的时候会报错的。
@FunctionalInterface
interface Converter<F, T> {
    T convert(F from);
}
Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted);    // 123

需要注意如果@FunctionalInterface如果没有指定,上面的代码也是对的。

四、方法与构造函数引用

方法的所有者::方法名
a.通过类引用其中的静态方法
    类名::静态方法名
b.通过对象引用其中的非静态方法
    对象名::非静态方法名
c.通过类引用它的构造方法
    类名::new 
d.通过数组引用它的构造方法
    数据类型[]::new
前一节中的代码还可以通过静态方法引用来表示:
Converter<String, Integer> converter = Integer::valueOf;
Integer converted = converter.convert("123");
System.out.println(converted);   // 123

Java 8 允许你使用 :: 关键字来传递方法或者构造函数引用,上面的代码展示了如何引用一个静态方法,我们也可以引用一个对象的方法:

converter = something::startsWith;
String converted = converter.convert("Java");
System.out.println(converted);    // "J"

接下来看看构造函数是如何使用::关键字来引用的,首先我们定义一个包含多个构造函数的简单类:

class Person {
    String firstName;
    String lastName;

    Person() {}

    Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}
interface PersonFactory<P extends Person> {
    P create(String firstName, String lastName);
}
PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.create("Peter", "Parker");

我们只需要使用 Person::new 来获取Person类构造函数的引用,Java编译器会自动根据PersonFactory.create方法的签名来选择合适的构造函数。

 
 
 
 


作者:一入码坑深似海
链接:https://www.jianshu.com/p/0bf8fe0f153b
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
原文地址:https://www.cnblogs.com/xiaozhang666/p/13188367.html