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<>()