我是靠谱客的博主 安静汽车,最近开发中收集的这篇文章主要介绍《写给大忙人看的java SE8》笔记 -- 1. lambda表达式,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

函数式接口

只含有一个抽象方法的接口,称为函数式接口。lambda表达式可以赋值并且仅可以赋值给函数式接口的变量。实际上编译器往往需要根据函数式接口推断lambda表达式的参数类型和返回值,比如: Comparator<String> comp = (first, second) -> Integer.compare(first.length(), second.length())。实际上,你甚至无法将一个lambda表达式赋值给一个Object类型的对象。

java.util.function包定义了各种常用的函数式接口,不过identity函数接口由Function类的静态方法提供。Runnable和Callable也是常见的函数接口。可以给函数式接口添加@FunctionalInterface标记,便于编译器检查。

lambda表达式语法

  • (String first, String second) -> { ...; return 0;}
  • (String first, String second) -> Integer.compare(first.length(), second.length()) //单条语句省略大括号
  • (first, second) ->  Integer.compare(first.length(), second.length()) //如果类型可推断
  • () -> { doWork();} //如果无参数
  • event -> System.out.println("button clicked") //只有一个参数且类型可推断,省略参数括号

函数引用

对象::实例方法

button.setOnAction(System.out::println) 等价于 button.setOnAction(event -> System.out.println(event)。对象可以是this或super,比如 this::equals 等价于 x -> this.equals(x)。

类::静态方法

Math::pow 等价于 (x,y) -> Math.pow(x,y)

类::实例方法

会在lambda表达式的第一个参数上调用该方法,比如 String::CompareTo 等价于 (x,y) -> x.compareTo(y)

构造函数引用

Button::new 等价于 x -> new Button(x)int[]::new 等价于 x -> new int[x]。可以避免泛型数组的限制,如Button[] btns = stream.toArray(Button[]::new);

作用域

lambda表达式方法体与嵌套代码块有着相同的作用域。实际上,如果方法体里引用了this,就和在嵌套块里引用this是一样的,指向的并不是lambda表达式对象。方法体里如果使用了外部的局部变量,则该变量必须是“有效的final”变量(即初始化之后不会再赋值,即便没有用final关键字修饰)。内部类原先的final约束也放宽为“有效final”。

默认方法

接口可以通过default关键字提供方法的默认实现(注意只能是接口)。

默认方法冲突的解决规则 1. 类优先。class Student extends Person implements Named {} 如果父类Person和接口Named具有同名方法,则继承父类的。2. 接口冲突。如果父类没有该方法,但是多个接口有同名方法,且至少一个接口提供了默认实现,则必须提供具体实现。

函数式接口与泛型

考虑List作为函数参数,如果函数只需要从List里面读取Person数据,那么参数可以定义为List<? extends Person>,这样传递一个List<Student>参数也没问题。如果函数只需要往List里面写入Student数据,参数可以定义为<? super Student>,这样传递一个List<Person>参数也没问题。一般来讲,读取是协变的(covariant,可以接受子类型),写入是逆变的(contravariant,可以接受父类型)。函数式接口也要遵守此惯例,比如Stream<T>的如下方法:

  • void forEach(Consumer<? super T> action)
  • Stream<T> filter(Predicate<? super T> predicate)
  • <R> Stream<R> map(Function<? super T, ? extends R> mapper)

也存在协变和逆变互相抵消的情况,这时就不需要通配符,比如 T reduce(T identity, BinaryOperator<T> accumulator)

一般来讲,你只需要在所有不是返回类型的参数类型上加上? super,并且在所有不是参数类型的返回类型上加上? extends。(simply add ? super to any argument type that is not also a return type, and ? extends to any return type that is not also an argument type.)

最后

以上就是安静汽车为你收集整理的《写给大忙人看的java SE8》笔记 -- 1. lambda表达式的全部内容,希望文章能够帮你解决《写给大忙人看的java SE8》笔记 -- 1. lambda表达式所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部