您的位置:首页 > 编程语言 > Java开发

java8新特性(一)

2018-02-09 00:00 302 查看
一、Lambda表达式和函数式接口

1、Lambda表达式(也就是闭包):它允许我们将一个函数当作方法的参数(传递函数),这是每个函数式编程者熟悉的概念。其实1.7以下就有支持Lambda表达式的,但是java程序员没有选择,只能使用匿名内部类来代替Lambda表达式。

简单的Lambda表达式:参数列表 -> 功能语句块
示例一:

Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );

示例二:

Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.println( e ) );

注意:编译器会根据上下文来推测参数的类型,或者你也可以显示地指定参数类型,只需要将类型包在括号里

示例三: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;
} );

2、函数式接口:语言的设计者们为了让现有的功能和Lambda表达式友好兼容,于是就有了函数式接口,函数式接口是一种只有一个方法的接口,函数式接口可以隐式的转换成Lambda表达式。

java.lang.Runnable和java.util.concurrent.Callable是函数式接口最好的两个例子。但是在实践中,函数接口是非常脆弱的,只要有人在接口里添加多一个方法,那么这个接口就不是函数接口了,就会导致编译失败。Java 8提供了一个特殊的注解@FunctionalInterface来克服上面提到的脆弱性并且显示地表明函数接口的目的(java里所有现存的接口都已经加上了@FunctionalInterface)。

简单的函数接口定义:

@FunctionalInterface
public interface Functional {
void method();
}

记住默认的方法和静态方法不会违反函数接口的约定,下面讲讲。

@FunctionalInterface
public interface FunctionalDefaultMethods {
void method();
default void defaultMethod() {
}
}

2.1、接口的默认方法和静态方法

默认方法:默认方法允许我们在接口里添加新的方法,而不会破坏实现这个接口的已有类的兼容性,也就是说不会强迫实现接口的类实现默认方法。

默认方法和抽象方法的区别是抽象方法必须要被实现,默认方法不是。作为替代方式,接口可以提供一个默认的方法实现,所有这个接口的实现类都会通过继承得倒这个方法(如果有需要也可以重写这个方法)

示例:

private interface Defaulable {
// Interfaces now allow default methods, the implementer may or
// may not implement (override) them.
default String notRequired() {
return "Default implementation";
}
}
private static
3ff0
class DefaultableImpl implements Defaulable {
}
private static class OverridableImpl implements Defaulable {
@Override
public String notRequired() {
return "Overridden implementation";
}
}

Java 8 的另外一个有意思的新特性是接口里可以声明静态方法,并且可以实现

private interface DefaulableFactory {
// Interfaces now allow static methods
static Defaulable create( Supplier< Defaulable > supplier ) {
return supplier.get();
}
}

接口的静态方法和默认方法放在一起的示例(::new 是构造方法引用,后面会有详细描述)

public static void main( String[] args ) {
Defaulable defaulable = DefaulableFactory.create( DefaultableImpl::new );
System.out.println( defaulable.notRequired() );

defaulable = DefaulableFactory.create( OverridableImpl::new );
System.out.println( defaulable.notRequired() );
}

控制台输出:

Default implementation
Overridden implementation

二、方法引用

方法引用提供了一个很有用的语义来直接访问类或者实例的已经存在的方法或者构造方法。java8中提供了4种方法引用,用Car类作示例

public static class Car {
public static Car create( final Supplier< Car > supplier ) {
return supplier.get();
}

public static void collide( final Car car ) {
System.out.println( "Collided " + car.toString() );
}

public void follow( final Car another ) {
System.out.println( "Following the " + another.toString() );
}

public void repair() {
System.out.println( "Repaired " + this.toString() );
}
}

1、构造方法引用

语法:Class :: new
泛型语法:Class<T> :: new
注意:构造方法没有参数

示例:

final Car car = Car.create( Car::new );
final List< Car > cars = Arrays.asList( car );

2、静态方法引用

语法:Class::static_method
注意:这个静态方法只支持一个类型为Car的参数

示例:

cars.forEach( Car::collide );

3、类实例的方法引用

语法:Class::method
注意:方法没有参数

示例:

cars.forEach( Car::repair );

4、引用特殊类的方法

语法:instance::method
注意:只接受Car类型的一个参数

示例:

final Car police = Car.create( Car::new );
cars.forEach( police::follow );

运行这些例子我们将会在控制台得到如下信息(Car的实例可能会不一样):

Collided com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d
Repaired com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d
Following the com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d

参考地址:http://ifeve.com/java-8-features-tutorial/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息