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 -> boolean IntPredicate, LongPredicate, DoublePredicate
Consumer<T> T -> void IntConsumer, LongConsumer, DoubleConsumer
Function<T, R> T -> R IntFunction<R>, IntToDoubleFunction, IntToLongFunction, LongFunction<R>, LongToDoubleFunction, LongToIntFunction, DoubleFunction<R>, ToIntFunction<T>, ToDoubleFunction<T>, ToLongFunction<T>
Supplier<T> () -> T BooleanSupplier, IntSupplier, LongSupplier, DoubleSupplier
UnaryOperator<T> T -> T IntUnaryOperator, LongUnaryOperator, DoubleUnaryOperator
BinaryOperator<T> (T, T) -> T IntBinaryOperator, LongBinaryOperator, DoubleBinaryOperator
BiPredicate<L, R> (L, R) -> boolean
BiConsumer<T, U> (T, U) -> void ObjIntConsumer<T>, ObjLongConsumer<T>, ObjDoubleConsumer<T>
BiFunction<T, U, R> (T, U) -> R ToIntBiFunction<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
page77image6336



相同的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);

类型推断
page80image16528
page80image16696


约束
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);

}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值