Java8 Lambda表达式

引入:通过 Runnable 接口创建线程的代码如下所示,代码中创建了一个实现 Runnable 接口的新对象, Runnable 接口只有一个方法,即 run方法,新对象实现了 run 方法,打印出一行字:真正的业务代码。实现了Runnable 接口的匿名内部类是传递了一种行为的对象,行为就是第7行的代码。此例中,程序只想传入行为,而非对象,真正的行为代码只有一行,但是调用这行业务代码却不得不多写几行样板代码,而且真正的业务代码还被隐藏在样板代码中。

	@Test
	public void createThread() {

		new Thread(new Runnable() {
			@Override
			public void run() { // TODO Auto-generated method stub
				System.out.println("真正的业务代码");
			}
		}).start();

	}
如何简洁地传入一种行为呢?在Java8中,可以用 Lambda 表达式:

	@Test
	public void createThread() {
		new Thread(() -> System.out.println("真正的业务代码")).start();
	}
经过改写之后,代码量减少了,业务代码更清晰了。与利用匿名内部类的不同实现之处在于,传入了一个代码块,-> 将参数和 Lambda 表达式分开,-> 前面的参数是 run 方法的参数,而->后面的表达式是 run 方法的内容。
Lambda 表达式的形式:

无参数,一个表达式:()->System.out.println("真正的业务代码");

一个参数(可省略参数的括号),一个表达式:(a)->System.out.println(a);

多个参数,一个表达式:(a,b)->a-b;

 Lambda 表达式也可以包含多行代码,此时需要把多行代码作为代码块放在花括号{}内。

区分Lambda 表达式最简单的方式是看代码中是否出现 -> 。

引用值,而非变量:

在 Lambda 表达式中,只能引用变量的值,而不能引用可变的变量,虽然变量不一定显式声明为 final 变量,但必须是 effectively final。

	@Test
	public void createThread() {
		String name = "name";
		// name = "changed name";
		new Thread(() -> System.out.println(name)).start();
	}
上面的代码中,若加入第4行,则编译报错:java.lang.Error: Unresolved compilation problem: Local variable name defined in an enclosing scope must be final or effectively

final,说明在 Lambda 表达式中,不能改变变量的值,即 Lambda 表达式只能引用相对 final 的值。

Lambda 表达式的类型:函数接口(@FunctionalInterface),简称 FI。

函数接口是只有一个抽象方法的接口,抽象方法是指这个函数接口本身所特有的方法,不包含从它的父类中继承过来的方法。开篇中的 Runnable 是一个函数接口,只有 run 一个抽象方法。Lambda 表达式可以实现 Runnable 接口并实现 run 方法,因此上述例子中 Lambda 表达式 参数其实就是 run 方法所需的参数。再举个例子,

匿名内部类实现,

public class LambdaTest {

	JButton button = new JButton();

	@Test
	public void buttonClicked() {

		button.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				// TODO Auto-generated method stub
				System.out.println("按钮被点击了");
			}
		});
	}

}
Lambda 表达式实现,

public class LambdaTest {

	JButton button = new JButton();

	@Test
	public void buttonClicked() {
		button.addActionListener(event -> System.out.println("按钮被点击了"));
	}

}
对比上述的2种实现监听按钮点击事件的方法,Lambda 表达式的参数 event 是 ActionListener 接口的 actionPerformed 方法的参数,仔细观察会发现Lambda 表达式的参数 event 没有声明类型,这是因为 Javac 可以根据 Lambda 表达式的上下文来推断参数的正确类型。正如本例中 event 的参数类型,是根据 ActionListener 接的 actionPerformed 方法的参数类型进行推断的。

在 Java8 中,函数接口以 @FunctionalInterface 类注解,重要且常见的函数接口有:



总结:Lambda 表达式是一个将行为作为数据传递的匿名方法;

           函数接口是仅有一个抽象方法的接口,是 Lambda 表达式的类型。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值