java8 lambda 匿名_jdk8 Lambda表达式与匿名内部类比较

Labmda表达式与匿名内部类

前言

Java Labmda表达式的一个重要用法是简化某些匿名内部类(Anonymous Classes)的写法。实际上Lambda表达式并不仅仅是匿名内部类的语法糖,JVM内部是通过invokedynamic指令来实现Lambda表达式的。具体原理放到下一篇。本篇我们首先感受一下使用Lambda表达式带来的便利之处。

取代某些匿名内部类

本节将介绍如何使用Lambda表达式简化匿名内部类的书写,但Lambda表达式并不能取代所有的匿名内部类,只能用来取代函数接口(Functional Interface)的简写。先别在乎细节,看几个例子再说。

例子1:无参函数的简写

如果需要新建一个线程,一种常见的写法是这样:

// JDK7 匿名内部类写法

class Anonymous {

public void anonymousStyle() {

new Thread(new Runnable() {

@Override

public void run() {

System.out.println("Anonymous style thread run ***************");

}

}).start();

}

}

上述代码给Tread类传递了一个匿名的Runnable对象,重载Runnable接口的run()方法来实现相应逻辑。这是JDK7以及之前的常见写法。匿名内部类省去了为类起名字的烦恼,但还是不够简化,在Java 8中可以简化为如下形式:

class Lambda {

public void lambdaStyle() {

new Thread(() -> System.out.println("Lambda Style thread run ******************")).start();

}

}

上述代码跟匿名内部类的作用是一样的,但比匿名内部类更进一步。这里连接口名和函数名都一同省掉了,写起来更加神清气爽。如果函数体有多行,可以用大括号括起来,就像这样:

// JDK8 Lambda表达式代码块写法

class Lambda {

public void lambdaStyle() {

new Thread(() -> {

System.out.println("lambda thread1 run********");

System.out.println("lambda thread2 run********");

}).start();

}

}

例子2:带参函数的简写

如果要给一个字符串列表通过自定义比较器,按照字符串长度进行排序,Java 7的书写形式如下:

/**

* JDK7 匿名内部类写法

*/

public void anonymousStyle() {

List names = Arrays.asList("cary", "jane", "jerry");

Collections.sort(names, new Comparator() {

@Override

public int compare(String o1, String o2) {

return o2.compareTo(o1);

}

});

for (String name : names) {

System.out.println("name:" + name);

}

}

上述代码通过内部类重载了Comparator接口的compare()方法,实现比较逻辑。采用Lambda表达式可简写如下:

/**

* JDK8 Lambda表达式写法

*/

public void lambdaStyle() {

List names = Arrays.asList("cary", "jane", "jerry");

Collections.sort(names, (o1, o2) -> {

if (o1 == null)

return -1;

if (o1 == null)

return 1;

return o1.length() - o2.length();

});

}

上述代码跟匿名内部类的作用是一样的。除了省略了接口名和方法名,代码中把参数表的类型也省略了。这得益于javac的类型推断机制,编译器能够根据上下文信息推断出参数的类型,当然也有推断失败的时候,这时就需要手动指明参数类型了。注意,Java是强类型语言,每个变量和对象都必需有明确的类型。

简写的依据

也许你已经想到了,能够使用Lambda的依据是必须有相应的函数接口(函数接口,是指内部只有一个抽象方法的接口)。这一点跟Java是强类型语言吻合,也就是说你并不能在代码的任何地方任性的写Lambda表达式。实际上Lambda的类型就是对应函数接口的类型。Lambda表达式另一个依据是类型推断机制,在上下文信息足够的情况下,编译器可以推断出参数表的类型,而不需要显式指名。Lambda表达更多合法的书写形式如下:

/**

* Created by cary on 2016/10/21.

*/

public class MyLambda {

public void lambda() {

Runnable run = () -> System.out.println("Thread run********");

ActionListener listener = event -> System.out.println("button clicked");

/**

* 代码块

*/

Runnable block = () -> {

System.out.println("Lambda 代码块******");

System.out.println("Lambda 代码块******");

};

BinaryOperator add = (Long x, Long y) -> x + y;

/**

* 5 类型推断

*/

BinaryOperator infer = (x, y) -> x + y;//

}

public static void main(String[] args) {

new MyLambda().lambda();

}

}

上述代码中,1展示了无参函数的简写;2处展示了有参函数的简写,以及类型推断机制;3是代码块的写法;4和5再次展示了类型推断机制。

参考文献

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值