Java8引入了一些新特性,其中值得关注的主要有以下几个:

Lambda表达式

Lambda表达式又称为闭包,是Java8函数式编程的基石,而且Lmada表达式允许将函数(即Lambda表达式)传递进方法中。
以往在进行数组排序,比如调用Arrays.sort()时,需要传入一个comparator实例,以匿名类(即直接new,不给名字)方式编写:

  1. String[] array = {"aa","ab","ac","ad"};
  2. Arrays.sort(array, new Comparator<String>() {
  3. @Override
  4. public int compare(String s1, String s2) {
  5. return s1.compareTo(s2);
  6. }
  7. });

这样的写法需要新建类,而后重载函数,较为繁琐,可以将其改为Lambda表达式的形式:

  1. Arrays.sort(array,(s1,s2)->{return s1.compareTo(s2);});

上式即是一个lambda表达式的写法。为了简洁也可以改成:

  1. Arrays.sort(array,(s1,s2)->s1.compareTo(s2));

其基本的语法格式为:

  1. (parameter1,parameter2,...)-> expression
  2. 或者:
  3. (parameter1,parameter2,...)->{expression1;expression2;......}

注:表达式只有一个就不需要大括号,反之亦反。
可见,Lambda表达式写法其实很简单:即写出方法的定义,相关的参数类型可以忽略,因为编译器会自动推断。

方法引用

方法引用让程序员可以直接引用已有的java类或者对象中的方法或构造器,可以使得整体程序代码更加的整洁。
接着上面的那个例子,先定一个类,包含compare方法。

  1. public class Main{
  2. static int compare(String s1,String s2){
  3. return s1.compareTo(s2);
  4. }
  5. }

那么想对一个数组进行排序,可以直接这样:

  1. Array.sort(array,Main::compare);

引出方法引用的定义:当方法签名一致时,可以通过::的方式直接指向一个方法,进行引用。
方法引用可以有四种引用方式

  • 静态方法引用:即上述例子的compare方法;
  • 实例方法引用:采用Classname::MethodName或Instance::MethodName;

注:在实例方法引用时,带有一个隐含的this参数,这就解释有时method只有一个参数,但是可以匹配两个参数的方法;

  • 构造函数引用:采用ClassName::new的方式;
  • 通用方法引用:采用ClassName::methodName;

详情可以参考:方法引用

函数式接口

函数式接口主要有:Predicate、Function、Supplier、Consumer。
这个可以直接参考另外一个文档

默认方法

默认方法是针对接口的补充,直接看例子:

  1. public interface Bee {
  2. default void print(){
  3. System.out.println("我是一只小蜜蜂~");
  4. }
  5. }

在JDK8之前,这样写是不对的!——因为接口只应该有声明,不应该有实现
简单来说,默认方法就是接口可以有实现方法,而且不需要具体的实现类去实现这些接口方法
有点懵——为什么需要这个特性?不是面向对象、面向接口编程么?怎么接口还有实现了?
这是为了解决“当需要修改接口的时候,需要修改全部实现该接口的类”,有了default,它可以在接口添加功能特性,并且不影响接口的实现类。而且考虑到旧版本的兼容问题,引进default方法来解决。
从下面这个例子就可以看出它到底有什么好处了:

  1. public class MyClass implements Mouth {
  2. public static void main(String[] args){
  3. }
  4. @Override
  5. public void saySomething() {
  6. // TODO Auto-generated method stub
  7. }
  8. }
  9. interface Mouth{
  10. public void saySomething();
  11. }

上述Myclass实现Mouth接口,如果在Mouth接口中增加一个SayHi()方法,如果不对Mouth进行实现,那么是编译不通过的,但是有可能这个类确确实实不需要这个方法,当真实现SayHi()不是浪费么!为了解决这个问题,我们只需要加上default即可:

  1. public class MyClass implements Mouth {
  2. public static void main(String[] args){
  3. }
  4. @Override
  5. public void saySomething() {
  6. // TODO Auto-generated method stub
  7. }
  8. }
  9. interface Mouth{
  10. public void saySomething();
  11. default public void sayHi(){
  12. System.out.println("Hi");
  13. }
  14. }

加了default的方法,在子类中不需要对其进行实现,还可以直接调用。
如果多接口存在冲突,要么在子类中重写该方法,要么利用supper指定调用。指定调用直接参考这个博客{ MyClass mc = new MyClass(); mc.sayHi(); } @Override public void saySomething() { // TODO Auto-generated method stub } @Override public void sayHi(){ InterfaceA.super.sayHi(); } } interface InterfaceA{ public void saySomething(); default public void sayHi(){ System.out.println(“Hi from InterfaceA”); } } interface InterfaceB{ default public void sayHi(){ System.out.println(“Hi from InterfaceB”); } })的例子:

  1. public class MyClass implements InterfaceA, InterfaceB {
  2. public static void main(String[] args){
  3. MyClass mc = new MyClass();
  4. mc.sayHi();
  5. }
  6. @Override
  7. public void saySomething() {
  8. // TODO Auto-generated method stub
  9. }
  10. @Override
  11. public void sayHi(){
  12. InterfaceA.super.sayHi();//重点!
  13. }
  14. }
  15. interface InterfaceA{
  16. public void saySomething();
  17. default public void sayHi(){
  18. System.out.println("Hi from InterfaceA");
  19. }
  20. }
  21. interface InterfaceB{
  22. default public void sayHi(){
  23. System.out.println("Hi from InterfaceB");
  24. }
  25. }

Stream

  1. +--------------------+ +------+ +------+ +---+ +-------+
  2. | stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
  3. +--------------------+ +------+ +------+ +---+ +-------+

Optional类

直接查看文档:Optional解析

参考资料

https://www.liaoxuefeng.com/wiki/1252599548343744/1305158055100449
https://blog.csdn.net/chszs/article/details/42612023