JDK8已经出来一段时间了,在此讲讲lambda表达式,lambda表达式可以理解为是对匿名对象的简化使用,可以将lambda表达式作为参数(这里的参数其实是一种接口类型)传递给方法,那在了解lambda表达式之前需要了解下什么是函数式接口?官方定义为:函数式接口是只含有一个抽象方法的普通接口,细心的朋友可能发现了在这里说到了抽象方法,那就有疑问了,接口里不都是抽象方法吗?为什么要刻意的提一下,确实在以前接口里都是抽象方法,但是在JDK8过后就不是这样了,增加了个新特性,接口里可以有默认实现,只需要加上default关键字就行,举个例子:
public interface Foo{
public abstract int calc(int a,int b);
public default int add(int a,int b){
return a + b;
}
}
在这里add方法就是一个默认实现,实现了该接口的类可以调用此默认实现的方法,也可以重写此方法。
public class Something implements Foo{
@override
public int calc(int a,int b){
return add(a,b);
}
}
看出来了吧,所以在JDK8过后,接口里面可以有默认实现,我认为增加这个特性是为了更好的践行面向接口编程思想。这方面就不多说,继续来说lambda表达式,定义好一个函数式接口(可以使用注解@FunctionalInterface来帮助你确实是正确定义了一个函数式接口)
@FunctionalInterface
public interface Foo{
public abstract int calc(int a,int b);
}
定义好函数式接口后就可以使用lambda表达式来生成该接口的实例,生成实例方式有如下几种(注意,下面不是根据上面的Foo接口的):
- 抽象方法含有两个参数:(int a, int b) -> { return a + b; }
- 抽象方法含有两个参数: (a, b) -> a + b
- 抽象方法含有一个参数:a -> a * a
- 抽象方法没有参数:() -> a
- 抽象方法void类型:a -> { System.out.println(a); }
没有列举完,看到这么多种应该明白了规则吧,注意:这里有些参数带有类型,有些参数没有类型,没有类型这是因为Java可以推导出参数类型,让代码更简洁
下面我们来用代码演示一下,我们就用上面的Foo接口来做演示。
因为Foo接口是一个函数式接口,只有一个抽象方法,不管是以前还是lambda表达式我们都只需要实现这一个抽象方法就能构建出他的实例。
以前的方式:
Foo foo = new Foo(){
@override
public int calc(int a,int b){
return a * b;
}
}
foo.calc(3,4) //12
使用lambda表达式,我们还是只注重calc方法的重写
用Java推导类型的方式:
Foo foo = (a,b)->a * b
foo.calc(3,4) //12
用指定参数类型的方式:
Foo foo = (int a,int b)->{return a * b}
foo.calc(3,4) //12
解释:左边为函数式接口中抽象方法的参数,右边不带{}为返回值带有{}为代码块。个人建议:最好是使用代码块,方便阅读。
这样就完成了使用lambda表达式来创建接口实例,是不是很方便。
在实际中的应用:
在Android中常用的就是事件的监听,举个例子,Button的点击事件监听。
@Bind(R.id.btn)
Button btn;
btn.setOnCLickListener(view->{Log.i("Button被点击了")});
lambda基础用法就说到这里,我认为在使用匿名对象的时候考虑使用lambda表达式是再好不过的选择,前提必须是个函数式接口。