笔者认识到的java比较重要的阶段是java5以及java8。
这里记录java8的一些新特性
一、Lambda表达式和函数式接口
Lambda读音和数学的λ读音一样,Lambda表达式也叫闭包,它允许我们将函数当成参数传递给某个方法,或者把代码本身当作数据处理。
Lambda表达式可由逗号分隔的参数列表、->符号和语句块组成,例如:
Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );
在上面这个代码中的参数e的类型是由编译器推理得出的,你也可以显式指定该参数的类型,例如:
Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.println( e ) );
如果Lambda表达式需要更复杂的语句块,则可以使用花括号将该语句块括起来,类似于Java中的函数体,例如:
Arrays.asList( "a", "b", "d" ).forEach( e -> {
System.out.print( e );
System.out.print( e );
} );
Lambda表达式可以引用类成员和局部变量(会将这些变量隐式得转换成final的),例如下列两个代码块的效果完全相同:
String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach(
( String e ) -> System.out.print( e + separator ) );
和
final String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach(
( String e ) -> System.out.print( e + separator ) );
Lambda表达式有返回值,返回值的类型也由编译器推理得出。如果Lambda表达式中的语句块只有一行,则可以不用使用return语句,下列两个代码片段效果相同:
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );
和
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> {
int result = e1.compareTo( e2 );
return result;
} );
函数接口:只有一个函数(方法)的接口,这样的接口可以隐式转换为Lambda表达式,例如java.lang.Runnable和java.util.concurrent.Callable。函数式接口非常脆弱:只要某个开发者在该接口中添加一个函数,则该接口就不再是函数式接口进而导致编译失败。为了尽量避免,并显式说明某个接口是函数式接口,Java 8 提供了一个特殊的注解@FunctionalInterface
@FunctionalInterface
public interface Functional {
void method();
}
注:默认方法和静态方法不会破坏函数式接口的定义,因此如下的代码是合法的。
@FunctionalInterface
public interface FunctionalDefaultMethods {
void method();
default void defaultMethod() {
}
static FunctionalDefaultMethods create( ) {
...
}
}
二、接口的默认方法和静态方法
Java 8使用两个新概念扩展了接口的含义:默认方法和静态方法。
默认方法,使得在现有接口中添加新的方法得到实现,即不强制那些实现了该接口的类也同时实现这个新加的方法。
接口提供的默认方法会被接口的实现类继承或者覆写,如下:
private interface Defaulable {
default String notRequired() {
return "Default implementation";
}
}
private static class DefaultableImpl implements Defaulable {
}
private static class OverridableImpl implements Defaulable {
@Override
public String notRequired() {
return "Overridden implementation";
}
}
Java 8带来的另一个特性是在接口中可以定义静态方法,如下:
private interface DefaulableFactory {
static Defaulable create( Supplier< Defaulable > supplier ) {
return supplier.get();
}
}
小结:默认方法允许在不打破现有继承体系的基础上改进接口。该特性在官方库中的应用是:给java.util.Collection接口添加新方法,如stream()、parallelStream()、forEach()和removeIf()等等。但使用时也需谨慎,可能带来语义分歧和编译错误。