Java函数式编程:一、函数式接口,lambda表达式和方法引用( 二 )


lambda表达式的语法如下所示:

  • 参数
  • -> , 它可以读作产生(produces)
  • 方法体
msg -> msg + "!";msg -> msg.upperCase();() -> "hello world";h -> {System.out.println(h + "abcdefg");return h.lowerCase();}有以下这些问题需要注意:
  • lambda表达式如果只有一个参数,可以只写该参数不写括号,但你要知道这是一种特殊情况而不是相反
  • 通常需要括号将参数包裹起来,为了一致性考虑,单个参数时也可以使用括号
  • 没有参数时 , 必须要有括号指代输入的参数
  • 存在多个参数时必须要以括号包裹,逗号分割
  • 如果一句话就可以表示返回值 , 那么就直接写到方法体所在的位置,此时return关键字是不合法的
  • 如果一句话无法囊括,那么就需要使用花括号将所有函数体包裹并以return返回结果
与内部匿名类相比,lambda表达式的可读性极佳,所以如果你需要使用这样的方法,你应该掌握lambda表达式 。
注意,如果你要利用lambda表达式实现递归调用自身的话,必须要将该表达式赋值给一个静态变量或一个实例变量 , 否则该语句对于编译器可能过于复杂,会产生编译错误 。
3、方法引用方法引用指向的是方法,通过类名或对象名 , 跟::,然后跟方法名就可以实现方法引用,注意,这种方法并不需要在方法名后面加上参数列表 。
className::method; // 注意,没有括号!我们可以通过一个接口 , 引用那些签名 (方法的参数类型数量以及返回类型) 一致的方法 。
需要注意的是,任何方法要被引用,都需要该方法存在其绑定对象,这个对象对于静态方法而言就是其Class对象,而对于普通方法而言,则需要确保存在该类对象 。
该对象要么被你创建出来并显式的赋给方法引用,类似这样
Object o = new o;method(o::methodName);这样我们的编译器就知道,这个方法是由我们的对象o来运行的,非常的明确 。
但是,还有一种情况就是未绑定的方法引用,即尚未关联到某个对象的普通方法 。对于这种引用,必须先提供对象,才能进行使用 。
interface Showable{String show(Show1 s);}class Show1{public String show(){return "hello world";}}public class test {public static void main(String[] args){Show1 s = new Show1();Showable sa = Show1::show;System.out.println(s.show());// 关键就在这里,我们知道这里sa实际上没有实例,show()当然无法调用 , 但实际上这里最终会调用到对象s的show()方法// 实际上,这里Java知道,它必须接受这个参数s,并且在s上面调用方法// 如果方法有更多参数 , 只需遵循第一个参数取得是this这种模式System.out.println(sa.show(s));}}若不只一个参数 , 则如下
public class test {public static void main(String[] args){Show1 s = new Show1();Showable sa = Show1::show;System.out.println(s.show(1, 2));System.out.println(sa.show(s, 1, 2));}}interface Showable{String show(Show1 s, int a, int b);}class Show1{public String show(int a, int b){return "hello world";}}实际上,除了普通的方法外,我们还可以通过new代替方法名来引用其构造器方法,这也是非常有用的,由于构造器方法实际上绑定该类 , 相当于静态方法,所以我们只需要通过接口直接调用即可 。

推荐阅读