java8新特性(二):Lambda表达式

一、什么是Lambda表达式

    上一篇中已经看到了Lambda表达式的使用场景,这一篇深入学习一下Java8的这个新特性。

     首先Lambda说一下表达式的定义:它是一个简洁的可以用于传递的匿名函数。 包含以下一些特性:

     1- 它是匿名的: 它不像不通的方法那样有一个明确的名称。

     2- 它是一个函数: 因为它不属于某个特定的类,但是它有参数列表、函数体、返回类型、和异常列表。

     3- 它可以被传递: 可以当成参数传递给一个方法,或者存储在一个变量当中。

     4- 它是简洁的:不需要像匿名类那样写很多冗余的代码。

 

 

Lambda表达式的结构:

       

 

没有Lambda表达式 之前写一个匿名类是这样写的:

Comparator<Apple> byWeight = new Comparator<Apple>() {

public int compare(Apple a1, Apple a2){

     return a1.getWeight().compareTo(a2.getWeight());

}

};

有了Lambda表达式 之后:

Comparator<Apple> byWeight = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());

 

Lambda表达式的基本语法有两种形式

一种表达式语法,不带花挂号 :(parameters) -> expression

表达式最后一句就是返回值,不需要显示的return语句。

或者

一种是语句语法,带有花挂号:(parameters) -> { statements; }

带花挂号的必须是完整的语句,不能写表达式。

 

例子

用例lambda表达式实例
布尔表达式(List<String> list) -> list.isEmpty()
创建对象() -> new Apple(10)
消费一个对象(Apple a) -> { System.out.println(a.getWeight()); }
抽取对象属性(String s) -> s.length()
合并两个值(int a, int b) -> a * b
比较两个对象(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())

 

二、Lambda表达式的使用场景

你可以在函数式接口上下文的环境中使用Lambda表达式。

 

那么什么是函数式接口呢? 简要的说函数式接口就是有且只有一个抽象方法的接口.

 

 

 

 

三、函数描述器

定义:函数描述器是函数接口的抽象方法的方法签名,从本质上描述Lambda表达式的签名,我们称这种抽象方法为函数描述器。

举例来说,Runnable接口就可以被描述为一个函数接口的签名,它没有参数没有返回值。

 

Java 8 中通用的函数没描述器

函数接口函数描述器基本类型函数接口
Predicate<T>T -> booleanIntPredicate, LongPredicate, DoublePredicate
Consumer<T>T -> voidIntConsumer, LongConsumer, DoubleConsumer
Function<T, R>T -> RIntFunction<R>, IntToDoubleFunction, IntToLongFunction, LongFunction<R>, LongToDoubleFunction, LongToIntFunction, DoubleFunction<R>, ToIntFunction<T>, ToDoubleFunction<T>, ToLongFunction<T>
Supplier<T>() -> TBooleanSupplier, IntSupplier, LongSupplier, DoubleSupplier
UnaryOperator<T>T -> TIntUnaryOperator, LongUnaryOperator, DoubleUnaryOperator
BinaryOperator<T>(T, T) -> TIntBinaryOperator, LongBinaryOperator, DoubleBinaryOperator
BiPredicate<L, R>(L, R) -> boolean 
BiConsumer<T, U>(T, U) -> voidObjIntConsumer<T>, ObjLongConsumer<T>, ObjDoubleConsumer<T>
BiFunction<T, U, R>(T, U) -> RToIntBiFunction<T, U>, ToLongBiFunction<T, U>, ToDoubleBiFunction<T, U>

 

由于java 中基本类型和包装类型 之间可以自动实现相互转化,叫做boxing 和unboxing。

但是这个过程会带来性能的开销。所以在java8 中提供了基本类型的功能接口。

 

 

四、类型检查、类型推断、约束

 

Lambda表达式没有明确的类型说明, 它的类型会根据它所在的上下文推断。

 

 

Figure 3.4. Deconstructing the type-checking process of a lambda expression

 

 

 

相同的Lambda表达式,不同的功能接口。

 

 

Callable<Integer> c = () -> 42;

PrivilegedAction<Integer> p = () -> 42;

 

Comparator<Apple> c1 = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());

 

ToIntBiFunction<Apple, Apple> c2 = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());

 

BiFunction<Apple, Apple, Integer> c3 = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());

 

void 返回值可以兼容

// Predicate has a boolean return

Predicate<String> p = s -> list.add(s);

// Consumer has a void return

Consumer<String> b = s -> list.add(s);

 

类型推断

 

约束

lambda表达式可以 没有约束的捕获实例变量和静态变量,但是捕获局部变量时,被捕获的局部变量必须是final类型的或者effectively final的 (定义为final 或者  事实上的final类型),并且lambda表达式不能改变局部变量的值。

 

 

五、方法引用

方法引用可以让你重复使用现有的方法定义,并且像Lambda表达式一样传递他们,而且比lambda表达式更加简洁。

 

//引用普通方法

Converter<String, Integer> converter = Integer::valueOf;

 

//引用构造方法

PersonFactory<Person> personFactory = Person::new;

 

 

六、 Lambda表达式访问变量的作用域

 

 

public  void testLambdaScope(){
    //访问局部变量
    int num = 1;
    Converter<Integer, String> stringConverter =  (from) -> String.valueOf(from + num);
    String converted  = stringConverter.convert(2);     // 3
    System.out.println(converted);   // 3

    //访问成员变量
    Converter<Integer, String> stringConverter1 = (from) -> {
        outerNum = 23;
        return String.valueOf(from);
    };
    //访问静态变量
    Converter<Integer, String> stringConverter2 = (from) -> {
        outerStaticNum = 72;
        return String.valueOf(from);
    };


    //访问接口的 默认方法 是不行的
    Formula formula = (a) -> sqrt( a * 100);

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值