1.接口改进

      以前Java的接口里只能声明方法和定义常量,现在可以在接口里定义静态方法和默认方法

定义静态方法

      定义静态(static)方法带来的好处就是可以减少创建工具类的需求了。比如 java.util.Collection接口定义了一个集合,对于此接口实例操作的很多通用方法都是通过工具类 java.util.Collections来提供的,现在可以在接口里定义静态方法,我们就可以把工具类里的静态方法直接移到接口类里,不需要独立创建工具类了。

 

定义默认方法

      另一个改进是,可以在不破坏现有接口实现的前提下添加默认(default)方法。比如java.lang.Iterable 接口现在拥有一个默认的 forEach 方法:

public default void forEach(Consumer<? super T> action) {
     Objects.requireNonNull(action);
     for (T t : this) {
          action.accept(t);
     }
}

 默认方法不能覆盖 equals, hashCode, toString 方法

 一个接口不能提供Object类里的任何方法的默认实现。这意味着不能在接口里提供 equals, hashCode, toString 方法的默认实现。

 

2.函数接口

       函数接口是Java8引入的一个核心概念。如果一个接口只定义了一个抽象方法,它就是函数接口。例如java.lang.Runnable就是一个函数接口,因为它只定义了一个抽象方法: public void run()。

默认方法不是抽象的,所以一个函数接口可以定义任意多的默认方法。

新引入的注解 @FunctionalInterface 用来表明接口准备成为函数接口,但不管有没有这个注解,编译器都认为只有一个抽象方法的接口是函数接口。

 

3.Lambdas

       函数接口一个极具价值的属性是可以在lambdas里实例化。下面是lambdas的一些实例:

(param1 ParamType1,  param2 ParamTeyp2, ... )  ->  {  statements;  }          //  lambdas 完整形式
 
(int x, int y) -> { return x + y; }          //  完整输入参数类型,具有返回语句的语句块
 
(x, y) -> x + y       //  自动类型推导参数类型,语句块只有一条 return 语句时可以省略大括号和return关键字,
 
x  ->  x * x          //  只有一个输入参数,可以省略入参列表的小括号。
 
()  ->  x            //  如果没有入参,小括号不能省略。
 
x  ->  { System.out.println(x); }     //  没有返回语句,语句块的大括号不能省略。

 

4.方法引用

  静态方法引用: String::valueOf。

  非静态方法引用: Object::toString。

  构造函数引用: ArrayList::new。

  捕获方法引用: x::toString。

  方法引用等价的lambda表达式:

String::valueOf          x -> String.valueOf(x)
  Object::toString         x -> x.toString()
  ArrayList::new           () -> new ArrayList<>()